Merge branch 'jokob-sk:main' into main

This commit is contained in:
Scott Roach
2023-10-04 17:54:07 -07:00
committed by GitHub
17 changed files with 517 additions and 26 deletions

View File

@@ -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]

View File

@@ -823,7 +823,7 @@ input[readonly] {
display: block;
position: absolute;
margin-left: 170px;
top: -3px;
top: 5px;
font-size: large;
left: -15px;
}

View File

@@ -325,7 +325,7 @@
<div class="form-group" title="<?= lang('DevDetail_Network_Node_hover');?>">
<label class="col-sm-3 control-label"><?= lang('DevDetail_MainInfo_Network');?></label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group parentNetworkNode">
<input class="form-control" id="txtNetworkNodeMac" type="text" value="--">
<span class="input-group-addon"><i title="<?= lang('DevDetail_GoToNetworkNode');?>" class="fa fa-square-up-right pointer" onclick="goToNetworkNode('txtNetworkNodeMac');"></i></span>
@@ -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();
}
}
</script>

View File

@@ -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 )) ? "<div class='netIcon ' ><i class='fa fa-"+nodeData.data.icon +"'></i></div>" : "";
devicePort = `<div class='netPort ' style="width:${emSize*2.7}em;height:${emSize*2.7}em" >${port}</div> <div class="portBckgIcon" style="margin-left:-${emSize*2.5}em;">${portBckgIcon}</div>`;
devicePort = `<div class='netPort ' style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em" >${port}</div> <div class="portBckgIcon" style="margin-left:-${emSize*sizeCoefficient}em;">${portBckgIcon}</div>`;
collapseExpandIcon = nodeData.data.hiddenChildren ? "square-plus" :"square-minus";
collapseExpandHtml = (nodeData.data.hasChildren) ? "<div class='netCollapse' style='font-size:"+emSize*2.5+"em;' data-mytreepath='"+nodeData.data.path+"' data-mytreemac='"+nodeData.data.mac+"'><i class='fa fa-"+ collapseExpandIcon +" pointer'></i></div>" : "";
collapseExpandHtml = (nodeData.data.hasChildren) ? "<div class='netCollapse' style='font-size:"+emSize*sizeCoefficient+"em;' data-mytreepath='"+nodeData.data.path+"' data-mytreemac='"+nodeData.data.mac+"'><i class='fa fa-"+ collapseExpandIcon +" pointer'></i></div>" : "";
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);
}

View File

@@ -857,8 +857,6 @@ function getDevices() {
function getDeviceTypes() {
global $db;
$networkTypes = getNetworkTypes();
// SQL
$sql = 'SELECT DISTINCT 9 as dev_Order, dev_DeviceType
FROM Devices

View File

@@ -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 <b><i class=\"fa fa-info-circle\"></i> Details</b> tab of any device in <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Devices</b></a>, and assign it to a network <b><i class=\"fa fa-server\"></i> Node (MAC)</b> and <b><i class=\"fa fa-ethernet\"></i> Port</b> there.",
"Network_Root_Unconfigurable": "Unconfigurable root",
"HelpFAQ_Title" : "Help / FAQ",
"HelpFAQ_Cat_General" : "General",
"HelpFAQ_Cat_Detail" : "Details",

View File

@@ -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.

View File

@@ -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" : "<i class=\"fa-solid fa-gauge-high\"></i>"
}],
"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": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
},
{
"equals": "watched-changed",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
},
{
"equals": "new",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
},
{
"equals": "missing-in-last-scan",
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
}
],
"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 <code>schedule</code> the scheduling settings from below are applied. If you select <code>once</code> the scan is run only once on start of the application (container) for the time specified in <a href=\"#INTRSPD_RUN_TIMEOUT\"><code>INTRSPD_RUN_TIMEOUT</code> setting</a>."
}]
},
{
"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 <code>schedule</code> in the <a href=\"#INTRSPD_RUN\"><code>INTRSPD_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes."
},
{
"language_code": "es_es",
"string": "Solo habilitado si selecciona <code>schedule</code> en la configuración <a href=\"#INTRSPD_RUN\"><code>INTRSPD_RUN</code></a>. Asegúrese de ingresar el schedule en el formato similar a cron correcto (por ejemplo, valide en <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). Por ejemplo, ingrese <code >0 4 * * *</code> ejecutará el escaneo después de las 4 am en el <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> que configuró arriba </a>. 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 <code>CTRL + Click</code> to select/deselect. <ul> <li><code>Watched_Value1</code> is Download speed (not recommended)</li><li><code>Watched_Value2</code> is Upload speed (not recommended)</li><li><code>Watched_Value3</code> unused </li><li><code>Watched_Value4</code> unused </li></ul>"
}]
},
{
"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. <code>new</code> means a new unique (unique combination of PrimaryId and SecondaryId) object was discovered. <code>watched-changed</code> means that selected <code>Watched_ValueN</code> columns changed."
},
{
"language_code": "es_es",
"string" : "Envíe una notificación solo en estos estados. <code>new</code> significa que se descubrió un nuevo objeto único (combinación única de PrimaryId y SecondaryId). <code>watched-changed</code> significa que seleccionó <code>Watched_ValueN Las columnas </code> cambiaron."
}]
}
]
}

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -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())

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -0,0 +1 @@
This plugin will not be loaded

View File

@@ -295,12 +295,8 @@
}],
"description": [{
"language_code": "en_us",
"string" : "Enable a regular scan of your services. If you select <code>schedule</code> the scheduling settings from below are applied. If you select <code>once</code> the scan is run only once on start of the application (container) for the time specified in <a href=\"#INTRSPD_RUN_TIMEOUT\"><code>INTRSPD_RUN_TIMEOUT</code> setting</a>."
},
{
"language_code": "es_es",
"string" : "Habilite un escaneo regular de sus servicios. Si selecciona <code>schedule</code>, se aplican las configuraciones de programación de abajo. Si selecciona <code>once</code>, el escaneo se ejecuta solo una vez al iniciar la aplicación (contenedor) durante el tiempo especificado en <a href=\"#INTRSPD_RUN_TIMEOUT\"><code>INTRSPD_RUN_TIMEOUT</code> configuración</a>."
}]
"string" : "Enable a regular internet speedtest. If you select <code>schedule</code> the scheduling settings from below are applied. If you select <code>once</code> the scan is run only once on start of the application (container) for the time specified in <a href=\"#INTRSPD_RUN_TIMEOUT\"><code>INTRSPD_RUN_TIMEOUT</code> setting</a>."
}]
},
{
"function": "CMD",

View File

@@ -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,