🔄Sync hub 2.0

This commit is contained in:
jokob-sk
2024-09-14 09:37:27 +10:00
parent 99fb60c1b5
commit aefe470d31
4 changed files with 190 additions and 8 deletions

View File

@@ -159,6 +159,81 @@
"string": "Encryption key used to encrypt the data before sending and for decryption on the hub. The key needs to be the same on the hub and on the nodes."
}
]
},{
"function": "nodes",
"type": {
"dataType": "array",
"elements": [
{
"elementType": "input",
"elementOptions": [
{ "placeholder": "Enter full url" },
{ "suffix": "_in" },
{ "cssClasses": "col-sm-10" },
{ "prefillValue": "null" }
],
"transformers": []
},
{
"elementType": "button",
"elementOptions": [
{ "sourceSuffixes": ["_in"] },
{ "separator": "" },
{ "cssClasses": "col-xs-12" },
{ "onClick": "addList(this, false)" },
{ "getStringKey": "Gen_Add" }
],
"transformers": []
},
{
"elementType": "select",
"elementHasInputValue": 1,
"elementOptions": [
{ "multiple": "true" },
{ "readonly": "true" },
{ "editable": "true" }
],
"transformers": []
},
{
"elementType": "button",
"elementOptions": [
{ "sourceSuffixes": [] },
{ "separator": "" },
{ "cssClasses": "col-xs-6" },
{ "onClick": "removeAllOptions(this)" },
{ "getStringKey": "Gen_Remove_All" }
],
"transformers": []
},
{
"elementType": "button",
"elementOptions": [
{ "sourceSuffixes": [] },
{ "separator": "" },
{ "cssClasses": "col-xs-6" },
{ "onClick": "removeFromList(this)" },
{ "getStringKey": "Gen_Remove_Last" }
],
"transformers": []
}
]
},
"default_value": [],
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Nodes [h]"
}
],
"description": [
{
"language_code": "en_us",
"string": "If specified, the hub will pull Devices data from the listed nodes."
}
]
},
{
"function": "hub_url",

View File

@@ -3,8 +3,11 @@
// External files
require '/app/front/php/server/init.php';
$method = $_SERVER['REQUEST_METHOD'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// ----------------------------------------------
// Method to check authorization
function checkAuthorization($method) {
// Retrieve the authorization header
$headers = apache_request_headers();
$auth_header = $headers['Authorization'] ?? '';
@@ -14,16 +17,56 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($auth_header !== $expected_token) {
http_response_code(403);
echo 'Forbidden';
write_notification("[Plugin: SYNC] Incoming data: Incorrect API Token", "alert");
write_notification("[Plugin: SYNC] Incoming data: Incorrect API Token (".$method.")", "alert");
exit;
}
}
// ----------------------------------------------
// Function to return JSON response
function jsonResponse($status, $data = [], $message = '') {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode([
'node_name' => getSettingValue('SYNC_node_name'),
'status' => $status,
'message' => $message,
'data' => $data,
'timestamp' => date('Y-m-d H:i:s')
]);
}
// ----------------------------------------------
// MAIN
// ----------------------------------------------
// requesting data (this is a NODE)
if ($method === 'GET') {
checkAuthorization($method);
$file_path = "/app/front/api/table_devices.json";
$data = file_get_contents($file_path);
// Prepare the data to return as a JSON response
$response_data = [
'data_base64' => base64_encode($data),
];
// Return JSON response
jsonResponse(200, $response_data, 'OK');
}
// receiving data (this is a HUB)
else if ($method === 'POST') {
checkAuthorization($method);
// Retrieve and decode the data from the POST request
$data = $_POST['data'] ?? '';
$plugin_folder = $_POST['plugin_folder'] ?? '';
$node_name = $_POST['node_name'] ?? '';
$storage_path = "/app/front/plugins/{$plugin_folder}";
// Create the storage directory if it doesn't exist
@@ -43,12 +86,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$file_path = "{$storage_path}/last_result.encoded.{$node_name}.{$file_count}.log";
// Save the decoded data to the file
file_put_contents($file_path, $data);
http_response_code(200);
echo 'Data received and stored successfully';
write_notification("[Plugin: SYNC] Data received ({$plugin_folder})", "info");
} else {
http_response_code(405);
echo 'Method Not Allowed';

View File

@@ -46,6 +46,7 @@ def main():
hub_url = get_setting_value('SYNC_hub_url')
node_name = get_setting_value('SYNC_node_name')
send_devices = get_setting_value('SYNC_devices')
pull_nodes = get_setting_value('SYNC_nodes')
# Get all plugin configurations
all_plugins = get_plugins_configs()
@@ -78,7 +79,9 @@ def main():
else:
mylog('verbose', [f'[{pluginName}] {plugin_folder}/last_result.log not found'])
# Devices procesing
# DEVICES sync
# PUSH/SEND (NODE)
if send_devices:
file_path = f"{INSTALL_PATH}/front/api/table_devices.json"
@@ -93,10 +96,40 @@ def main():
mylog('verbose', [f'[{pluginName}] Sending file_content: "{file_content}"'])
send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url)
# process any received data for the Device DB table
# Create the file path
# DEVICES sync
# PULL/GET (HUB)
file_dir = os.path.join(pluginsPath, 'sync')
file_prefix = 'last_result'
# pull data from nodes if specified
if len(pull_nodes) > 0:
for node_url in pull_nodes:
response_json, node_name = get_data(api_token, node_url)
# Extract node_name and base64 data
node_name = response_json.get('node_name', 'unknown_node')
data_base64 = response_json.get('data_base64', '')
# Decode base64 data
decoded_data = base64.b64decode(data_base64)
# Create log file name using node name
log_file_name = f'{file_prefix}.{node_name}.log'
# Write decoded data to log file
with open(file_path = os.path.join(file_dir, log_file_name), 'wb') as log_file:
log_file.write(decoded_data)
message = f'[{pluginName}] Data for "{plugin_folder}" from node "{node_name}" written to {log_file_name}'
mylog('verbose', [message])
write_notification(message, 'info', timeNowTZ())
# process any received data for the Device DB table
# Create the file path
# Decode files, rename them, and get the list of files
files_to_process = decode_and_rename_files(file_dir, file_prefix)
@@ -196,6 +229,7 @@ def main():
return 0
# send data to the HUB
def send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url):
# Encrypt the log data using the encryption_key
encrypted_data = encrypt_data(file_content, encryption_key)
@@ -223,6 +257,36 @@ def send_data(api_token, file_content, encryption_key, plugin_folder, node_name,
message = f'[{pluginName}] Failed to send data for "{plugin_folder}" (Status code: {response.status_code})'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowTZ())
# get data from the nodes to the HUB
def get_data(api_token, node_url):
mylog('verbose', [f'[{pluginName}] Getting data from node: "{node_url}"'])
# Set the authorization header with the API token
headers = {'Authorization': f'Bearer {api_token}'}
api_endpoint = f"{node_url}/plugins/sync/hub.php"
response = requests.get(api_endpoint, headers=headers)
# mylog('verbose', [f'[{pluginName}] response: "{response}"'])
if response.status_code == 200:
try:
# Parse JSON response
response_json = response.json()
return response_json
except json.JSONDecodeError:
message = f'[{pluginName}] Failed to parse JSON response from "{node_url}"'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowTZ())
return ""
else:
message = f'[{pluginName}] Failed to send data for "{plugin_folder}" (Status code: {response.status_code})'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowTZ())
return ""