diff --git a/docs/DEVICE_MANAGEMENT.md b/docs/DEVICE_MANAGEMENT.md index 73f5655c..3ee89cc3 100755 --- a/docs/DEVICE_MANAGEMENT.md +++ b/docs/DEVICE_MANAGEMENT.md @@ -11,7 +11,7 @@ To edit device information: > [!NOTE] > -> [Bulk-edit devices](/docs/DEVICES_BULK_EDITING.md) by using the `CSV Export` functionality in the `Maintenance` section. +> [Bulk-edit devices](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEVICES_BULK_EDITING.md) by using the `CSV Export` functionality in the `Maintenance` section. ![Device Details][screen1] diff --git a/front/css/pialert.css b/front/css/pialert.css index 4db3080d..a9d952f1 100755 --- a/front/css/pialert.css +++ b/front/css/pialert.css @@ -823,7 +823,7 @@ input[readonly] { display: block; position: absolute; margin-left: 170px; - top: -3px; + top: 5px; font-size: large; left: -15px; } diff --git a/front/deviceDetails.php b/front/deviceDetails.php index b3cf5aa2..d32a1f5c 100755 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -325,7 +325,7 @@
-
+
@@ -1295,8 +1295,8 @@ function getDeviceData (readAllData=false) { $('#txtNetworkNodeMac').attr ('data-mynodemac', deviceData['dev_Network_Node_MAC_ADDR']); $('#txtNetworkPort').val (deviceData['dev_Network_Node_port']); // disabling network node configuration if root Internet node - $('#txtNetworkNodeMac').prop('readonly', mac == 'Internet' ); - $('#txtNetworkPort').prop('readonly', mac == 'Internet' ); + toggleNetworkConfiguration(mac == 'Internet') + $('#txtFirstConnection').val (deviceData['dev_FirstConnection']); $('#txtLastConnection').val (deviceData['dev_LastConnection']); @@ -1398,8 +1398,6 @@ function performSwitch(direction) getDeviceData (true); - // reload current tab - reloadTab() } // ----------------------------------------------------------------------------- @@ -1796,15 +1794,27 @@ window.onload = function async() { initializeTabsNew(); - reloadTab(); + } //----------------------------------------------------------------------------------- - -function reloadTab() +// Disables network configuration for the root node +function toggleNetworkConfiguration(disable) { - // tab loaded without switching + $('#txtNetworkNodeMac').prop('readonly', true ); // disable direct input as should only be selected via the dropdown + if(disable) + { + $('#txtNetworkNodeMac').val(getString('Network_Root_Unconfigurable')); + $('#txtNetworkPort').val(getString('Network_Root_Unconfigurable')); + $('#txtNetworkPort').prop('readonly', true ); + $('.parentNetworkNode .input-group-btn').hide(); + } + else + { + $('#txtNetworkPort').prop('readonly', false ); + $('.parentNetworkNode .input-group-btn').show(); + } } diff --git a/front/network.php b/front/network.php index 9dc6dc16..a8c6ddcc 100755 --- a/front/network.php +++ b/front/network.php @@ -551,7 +551,8 @@ // --------------------------------------------------------------------------- function getHierarchy() - { + { + for(i in deviceListGlobal) { if(deviceListGlobal[i].mac == 'Internet') @@ -613,6 +614,7 @@ var treeAreaHeight = 800; var emSize; var nodeHeight; + var sizeCoefficient = 1 function initTree(myHierarchy) { @@ -640,9 +642,9 @@ // Build HTML for individual nodes in the network diagram deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ? "
" : ""; - devicePort = `
${port}
${portBckgIcon}
`; + devicePort = `
${port}
${portBckgIcon}
`; collapseExpandIcon = nodeData.data.hiddenChildren ? "square-plus" :"square-minus"; - collapseExpandHtml = (nodeData.data.hasChildren) ? "
" : ""; + collapseExpandHtml = (nodeData.data.hasChildren) ? "
" : ""; statusCss = " netStatus-" + nodeData.data.status; selectedNodeMac = $(".nav-tabs-custom .active a").attr('data-mytabmac') @@ -680,9 +682,9 @@ relationnalField: "children", }); - console.log('vvvv') + console.log(myHierarchy) - console.log('^^^^^^^') + myTree.refresh(myHierarchy); } diff --git a/front/php/server/devices.php b/front/php/server/devices.php index f1d70029..7b7c3419 100755 --- a/front/php/server/devices.php +++ b/front/php/server/devices.php @@ -857,8 +857,6 @@ function getDevices() { function getDeviceTypes() { global $db; - $networkTypes = getNetworkTypes(); - // SQL $sql = 'SELECT DISTINCT 9 as dev_Order, dev_DeviceType FROM Devices diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index a3eaa753..2faee1ae 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -410,6 +410,7 @@ "Network_Parent" : "Parent network device", "Network_Cant_Assign" : "Can't assign the root Internet node as a child leaf node.", "Network_NoAssignedDevices" : "This network node does not have any assigned devices (leaf nodes). Assign one from bellow or go to the Details tab of any device in Devices, and assign it to a network Node (MAC) and Port there.", + "Network_Root_Unconfigurable": "Unconfigurable root", "HelpFAQ_Title" : "Help / FAQ", "HelpFAQ_Cat_General" : "General", "HelpFAQ_Cat_Detail" : "Details", diff --git a/front/plugins/README.md b/front/plugins/README.md index b8b115cd..69bf683a 100755 --- a/front/plugins/README.md +++ b/front/plugins/README.md @@ -41,7 +41,7 @@ > \** The Undiscoverables plugin (`UNDIS`) inserts only user-specified dummy devices. > [!NOTE] -> You soft-disable plugins via Settings or completely ignore plugins by placing a `ignore_plugin` file into the plugin directory. The difference is that ignored plugins don't show up anywhere in the UI (Settings, Device details, Plugins pages). The app skips ignored plugins completely. Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however it makes sense to have a least some device-detecting plugins (that insert entries into the `CurrentScan` table) enabled, such as ARPSCAN or PIHOLE. +> You soft-disable plugins via Settings or completely ignore plugins by placing a `ignore_plugin` file into the plugin directory. The difference is that ignored plugins don't show up anywhere in the UI (Settings, Device details, Plugins pages). The app skips ignored plugins completely. Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however it makes sense to have a least some device-detecting plugins (that insert entries into the `CurrentScan` table) enabled, such as `ARPSCAN` or `PIHOLE`. > It's recommended to use the same schedule interval for all plugins responsible for discovering new devices. diff --git a/front/plugins/_publisher_apprise/config.json b/front/plugins/_publisher_apprise/config.json new file mode 100755 index 00000000..aaa42858 --- /dev/null +++ b/front/plugins/_publisher_apprise/config.json @@ -0,0 +1,417 @@ +{ + "code_name": "internet_speedtest", + "unique_prefix": "INTRSPD", + "enabled": true, + "data_source": "script", + "show_ui": true, + "localized": ["display_name", "description", "icon"], + "display_name" : [{ + "language_code": "en_us", + "string" : "Internet speedtest" + }], + "icon":[{ + "language_code": "en_us", + "string" : "" + }], + "description": [{ + "language_code": "en_us", + "string" : "A plugin to perform a scheduled internet speedtest." + }], + "params" : [], + "database_column_definitions": + [ + { + "column": "Index", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }, + { + "language_code": "es_es", + "string" : "N/A" + }] + }, + { + "column": "Plugin", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }, + { + "language_code": "es_es", + "string" : "N/A" + }] + }, + { + "column": "Object_PrimaryID", + "css_classes": "col-sm-2", + "show": false, + "type": "url", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }] + }, + { + "column": "Object_SecondaryID", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }, + { + "language_code": "es_es", + "string" : "N/A" + }] + }, + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Test run on" + }] + }, + { + "column": "DateTimeChanged", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Changed" + }, + { + "language_code": "es_es", + "string" : "Cambiado" + }] + }, + { + "column": "Watched_Value1", + "css_classes": "col-sm-2", + "show": true, + "type": "threshold", + "default_value":"", + "options": [ + { + "maximum": 1, + "hexColor": "#D33115" + }, + { + "maximum": 5, + "hexColor": "#792D86" + }, + { + "maximum": 10, + "hexColor": "#7D862D" + }, + { + "maximum": 100, + "hexColor": "#05483C" + } + ], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Download" + }] + }, + { + "column": "Watched_Value2", + "css_classes": "col-sm-2", + "show": true, + "type": "threshold", + "default_value":"", + "options": [ + { + "maximum": 1, + "hexColor": "#D33115" + }, + { + "maximum": 5, + "hexColor": "#792D86" + }, + { + "maximum": 10, + "hexColor": "#7D862D" + }, + { + "maximum": 100, + "hexColor": "#05483C" + } + ], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Upload" + }] + }, + { + "column": "Watched_Value3", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }, + { + "language_code": "es_es", + "string" : "N/A" + }] + }, + { + "column": "Watched_Value4", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "N/A" + }, + { + "language_code": "es_es", + "string" : "N/A" + }] + }, + { + "column": "UserData", + "css_classes": "col-sm-2", + "show": false, + "type": "textbox_save", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Comments" + }, + { + "language_code": "es_es", + "string" : "Comentarios" + }] + }, + { + "column": "Status", + "css_classes": "col-sm-1", + "show": false, + "type": "replace", + "default_value":"", + "options": [ + { + "equals": "watched-not-changed", + "replacement": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + }, + { + "equals": "missing-in-last-scan", + "replacement": "
" + } + ], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Status" + }, + { + "language_code": "es_es", + "string" : "Estado" + }] + }, + { + "column": "Extra", + "css_classes": "col-sm-3", + "show": false, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code": "en_us", + "string" : "Extra" + }, + { + "language_code": "es_es", + "string" : "Extra" + }] + } + ], + "settings":[ + { + "function": "RUN", + "events": ["run"], + "type": "text.select", + "default_value":"disabled", + "options": ["disabled", "once", "schedule", "always_after_scan" ], + "localized": ["name", "description"], + "name" :[{ + "language_code": "en_us", + "string" : "When to run" + }, + { + "language_code": "es_es", + "string" : "Cuando ejecuta" + }], + "description": [{ + "language_code": "en_us", + "string" : "Enable a regular internet speedtest. If you select schedule the scheduling settings from below are applied. If you select once the scan is run only once on start of the application (container) for the time specified in INTRSPD_RUN_TIMEOUT setting." + }] + }, + { + "function": "CMD", + "type": "readonly", + "default_value":"python3 /home/pi/pialert/front/plugins/internet_speedtest/script.py", + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code": "en_us", + "string" : "Command" + }, + { + "language_code": "es_es", + "string" : "Comando" + }], + "description": [{ + "language_code": "en_us", + "string" : "Command to run" + }, + { + "language_code": "es_es", + "string" : "Comando a ejecutar" + }] + }, + { + "function": "RUN_SCHD", + "type": "text", + "default_value":"*/30 * * * *", + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code": "en_us", + "string" : "Schedule" + }, + { + "language_code": "es_es", + "string" : "Schedule" + }], + "description": [{ + "language_code": "en_us", + "string" : "Only enabled if you select schedule in the INTRSPD_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." + }, + { + "language_code": "es_es", + "string": "Solo habilitado si selecciona schedule en la configuración INTRSPD_RUN. Asegúrese de ingresar el schedule en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingrese 0 4 * * * ejecutará el escaneo después de las 4 am en el TIMEZONE que configuró arriba . Se ejecutará la PRÓXIMA vez que pase el tiempo." + }] + }, + { + "function": "RUN_TIMEOUT", + "type": "integer", + "default_value":60, + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code": "en_us", + "string" : "Run timeout" + }, + { + "language_code": "es_es", + "string" : "Tiempo de espera de ejecución" + }, + { + "language_code": "de_de", + "string" : "Wartezeit" + }], + "description": [{ + "language_code": "en_us", + "string" : "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted." + }, + { + "language_code": "es_es", + "string" : "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela." + }] + }, + { + "function": "WATCH", + "type": "text.multiselect", + "default_value":[], + "options": ["Watched_Value1","Watched_Value2","Watched_Value3","Watched_Value4"], + "localized": ["name", "description"], + "name" :[{ + "language_code": "en_us", + "string" : "Watched" + }, + { + "language_code": "es_es", + "string" : "Visto" + }], + "description":[{ + "language_code": "en_us", + "string" : "Send a notification if selected values change. Use CTRL + Click to select/deselect.
  • Watched_Value1 is Download speed (not recommended)
  • Watched_Value2 is Upload speed (not recommended)
  • Watched_Value3 unused
  • Watched_Value4 unused
" + }] + }, + { + "function": "REPORT_ON", + "type": "text.multiselect", + "default_value":[], + "options": ["new","watched-changed","watched-not-changed", "missing-in-last-scan"], + "localized": ["name", "description"], + "name" :[{ + "language_code": "en_us", + "string" : "Report on" + }, + { + "language_code": "es_es", + "string" : "Informar sobre" + }] , + "description":[{ + "language_code": "en_us", + "string" : "Send a notification only on these statuses. new means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. watched-changed means that selected Watched_ValueN columns changed." + }, + { + "language_code": "es_es", + "string" : "Envíe una notificación solo en estos estados. new significa que se descubrió un nuevo objeto único (combinación única de PrimaryId y SecondaryId). watched-changed significa que seleccionó Watched_ValueN Las columnas cambiaron." + }] + } + ] +} diff --git a/front/plugins/_publisher_apprise/ignore_plugin b/front/plugins/_publisher_apprise/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_apprise/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/_publisher_apprise/script.py b/front/plugins/_publisher_apprise/script.py new file mode 100755 index 00000000..019d34dc --- /dev/null +++ b/front/plugins/_publisher_apprise/script.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Based on the work of https://github.com/leiweibau/Pi.Alert + +import argparse +import os +import pathlib +import sys +from datetime import datetime +import speedtest + +# Replace these paths with the actual paths to your Pi.Alert directories +sys.path.extend(["/home/pi/pialert/front/plugins", "/home/pi/pialert/pialert"]) + +from plugin_helper import Plugin_Objects +from logger import mylog, append_line_to_file +from helper import timeNowTZ + +CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) +RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') + +def main(): + + mylog('verbose', ['[APPRISE] In script']) + + parser = argparse.ArgumentParser(description='Speedtest Plugin for Pi.Alert') + values = parser.parse_args() + + plugin_objects = Plugin_Objects(RESULT_FILE) + speedtest_result = run_speedtest() + plugin_objects.add_object( + primaryId = 'Speedtest', + secondaryId = timeNowTZ(), + watched1 = speedtest_result['download_speed'], + watched2 = speedtest_result['upload_speed'], + watched3 = 'null', + watched4 = 'null', + extra = 'null', + foreignKey = 'null' + ) + plugin_objects.write_result_file() + +def run_speedtest(): + try: + st = speedtest.Speedtest() + st.get_best_server() + download_speed = round(st.download() / 10**6, 2) # Convert to Mbps + upload_speed = round(st.upload() / 10**6, 2) # Convert to Mbps + + return { + 'download_speed': download_speed, + 'upload_speed': upload_speed, + } + except Exception as e: + mylog('verbose', [f"Error running speedtest: {str(e)}"]) + return { + 'download_speed': -1, + 'upload_speed': -1, + } + +if __name__ == '__main__': + sys.exit(main()) diff --git a/front/plugins/_publisher_email/ignore_plugin b/front/plugins/_publisher_email/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_email/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/_publisher_mqtt/ignore_plugin b/front/plugins/_publisher_mqtt/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_mqtt/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/_publisher_ntfy/ignore_plugin b/front/plugins/_publisher_ntfy/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_ntfy/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/_publisher_pushsafer/ignore_plugin b/front/plugins/_publisher_pushsafer/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_pushsafer/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/_publisher_webhook/ignore_plugin b/front/plugins/_publisher_webhook/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/_publisher_webhook/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/internet_speedtest/config.json b/front/plugins/internet_speedtest/config.json index 67c5d1d6..aaa42858 100755 --- a/front/plugins/internet_speedtest/config.json +++ b/front/plugins/internet_speedtest/config.json @@ -295,12 +295,8 @@ }], "description": [{ "language_code": "en_us", - "string" : "Enable a regular scan of your services. If you select schedule the scheduling settings from below are applied. If you select once the scan is run only once on start of the application (container) for the time specified in INTRSPD_RUN_TIMEOUT setting." - }, - { - "language_code": "es_es", - "string" : "Habilite un escaneo regular de sus servicios. Si selecciona schedule, se aplican las configuraciones de programación de abajo. Si selecciona once, el escaneo se ejecuta solo una vez al iniciar la aplicación (contenedor) durante el tiempo especificado en INTRSPD_RUN_TIMEOUT configuración." - }] + "string" : "Enable a regular internet speedtest. If you select schedule the scheduling settings from below are applied. If you select once the scan is run only once on start of the application (container) for the time specified in INTRSPD_RUN_TIMEOUT setting." + }] }, { "function": "CMD", diff --git a/front/plugins/internet_speedtest/script.py b/front/plugins/internet_speedtest/script.py index 9df63aa2..10b65cc0 100755 --- a/front/plugins/internet_speedtest/script.py +++ b/front/plugins/internet_speedtest/script.py @@ -51,7 +51,7 @@ def run_speedtest(): 'upload_speed': upload_speed, } except Exception as e: - print(f"Error running speedtest: {str(e)}") + mylog('verbose', [f"Error running speedtest: {str(e)}"]) return { 'download_speed': -1, 'upload_speed': -1,