diff --git a/README.md b/README.md
index 9d6829f7..c9d9cb9a 100755
--- a/README.md
+++ b/README.md
@@ -56,9 +56,8 @@ Looking forward to your contributions if you decide to share your work with the
> - [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) - Lightweight network IP scanner with web GUI (Open source)
> - [Fing](https://www.fing.com/) - Network scanner app for your Internet security (Commercial, Phone App, Proprietary hardware)
-## ❤ Support me
+## ❤ Support me for...
-Get:
- Regular updates to keep your data and family safe 🔄
- Better and more functionality➕
- I don't get burned out and the app survives longer🔥🤯
diff --git a/front/devices.php b/front/devices.php
index f430d830..ace29af1 100755
--- a/front/devices.php
+++ b/front/devices.php
@@ -239,6 +239,8 @@ function main () {
// get visible columns
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Visible&skipcache', function(data) {
+
+ handle_locked_DB(data)
// save which columns are in the Devices page visible
tableColumnVisible = numberArrayFromString(data);
@@ -250,6 +252,8 @@ function main () {
// get the custom order specified by the user
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Order&skipcache', function(data) {
+
+ handle_locked_DB(data)
// save the columns order in the Devices page
tableColumnOrder = numberArrayFromString(data);
diff --git a/front/js/pialert_common.js b/front/js/pialert_common.js
index 97a30ce4..be9a9e58 100755
--- a/front/js/pialert_common.js
+++ b/front/js/pialert_common.js
@@ -346,10 +346,27 @@ function sanitize(data)
return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "")
}
+
+// -----------------------------------------------------------------------------
+// Check and handle locked database
+function handle_locked_DB(data)
+{
+ if(data.includes('database is locked'))
+ {
+ console.log(data)
+ showSpinner()
+
+ setTimeout(function() {
+ location.reload();
+ }, 5000);
+ }
+}
+
// -----------------------------------------------------------------------------
function numberArrayFromString(data)
{
- console.log(data)
+
+
data = JSON.parse(sanitize(data));
return data.replace(/\[|\]/g, '').split(',').map(Number);
}
diff --git a/front/maintenance.php b/front/maintenance.php
index 2843d819..aa429c50 100755
--- a/front/maintenance.php
+++ b/front/maintenance.php
@@ -816,6 +816,8 @@ function saveSelectedColumns () {
function initializeSelectedColumns () {
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+colDefaultOrderTxt+'¶meter=Front_Devices_Columns_Visible', function(data) {
+ handle_locked_DB(data)
+
tableColumnShow = numberArrayFromString(data);
for(i=0; i < tableColumnShow.length; i++)
diff --git a/front/plugins/db_cleanup/script.py b/front/plugins/db_cleanup/script.py
index 3f68d84e..94e3534f 100755
--- a/front/plugins/db_cleanup/script.py
+++ b/front/plugins/db_cleanup/script.py
@@ -25,6 +25,8 @@ CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
LOG_FILE = os.path.join(CUR_PATH, 'script.log')
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
+pluginName = 'DBCLNP'
+
def main():
parser = argparse.ArgumentParser(description='DB cleanup tasks')
@@ -40,13 +42,13 @@ def main():
DAYS_TO_KEEP_EVENTS = int(values.daystokeepevents.split('=')[1])
PHOLUS_DAYS_DATA = int(values.pholuskeepdays.split('=')[1])
- mylog('verbose', ['[DBCLNP] In script'])
+ mylog('verbose', [f'[{pluginName}] In script'])
# Execute cleanup/upkeep
cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST)
- mylog('verbose', ['[DBCLNP] Cleanup complete file '])
+ mylog('verbose', [f'[{pluginName}] Cleanup complete'])
return 0
@@ -58,25 +60,25 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
Cleaning out old records from the tables that don't need to keep all data.
"""
- mylog('verbose', ['[DBCLNP] Upkeep Database:' ])
+ mylog('verbose', [f'[{pluginName}] Upkeep Database:' ])
# Connect to the PiAlert SQLite database
conn = sqlite3.connect(dbPath)
cursor = conn.cursor()
# Cleanup Online History
- mylog('verbose', ['[DBCLNP] Online_History: Delete all but keep latest 150 entries'])
+ mylog('verbose', [f'[{pluginName}] Online_History: Delete all but keep latest 150 entries'])
cursor.execute ("""DELETE from Online_History where "Index" not in (
SELECT "Index" from Online_History
order by Scan_Date desc limit 150)""")
- mylog('verbose', ['[DBCLNP] Optimize Database'])
+ mylog('verbose', [f'[{pluginName}] Optimize Database'])
# Cleanup Events
- mylog('verbose', [f'[DBCLNP] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)'])
+ mylog('verbose', [f'[{pluginName}] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)'])
cursor.execute (f"""DELETE FROM Events
WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')""")
# Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry
- mylog('verbose', [f'[DBCLNP] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)'])
+ mylog('verbose', [f'[{pluginName}] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)'])
# Build the SQL query to delete entries that exceed the limit per unique "Plugin" column entry
delete_query = f"""DELETE FROM Plugins_History
@@ -97,7 +99,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
histCount = get_setting_value('DBCLNP_NOTIFI_HIST')
- mylog('verbose', [f'[DBCLNP] Plugins_History: Trim Notifications entries to less than {histCount}'])
+ mylog('verbose', [f'[{pluginName}] Plugins_History: Trim Notifications entries to less than {histCount}'])
# Build the SQL query to delete entries
delete_query = f"""DELETE FROM Notifications
@@ -115,20 +117,20 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
# Cleanup Pholus_Scan
if PHOLUS_DAYS_DATA != 0:
- mylog('verbose', ['[DBCLNP] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)'])
+ mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)'])
# todo: improvement possibility: keep at least N per mac
cursor.execute (f"""DELETE FROM Pholus_Scan
WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""")
# Cleanup New Devices
if HRS_TO_KEEP_NEWDEV != 0:
- mylog('verbose', [f'[DBCLNP] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)'])
+ mylog('verbose', [f'[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)'])
cursor.execute (f"""DELETE FROM Devices
WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""")
# De-dupe (de-duplicate) from the Plugins_Objects table
# TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :(
- mylog('verbose', ['[DBCLNP] Plugins_Objects: Delete all duplicates'])
+ mylog('verbose', [f'[{pluginName}] Plugins_Objects: Delete all duplicates'])
cursor.execute("""
DELETE FROM Plugins_Objects
WHERE rowid > (
@@ -141,7 +143,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
""")
# De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table
- mylog('verbose', ['[DBCLNP] Pholus_Scan: Delete all duplicates'])
+ mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all duplicates'])
cursor.execute ("""DELETE FROM Pholus_Scan
WHERE rowid > (
SELECT MIN(rowid) FROM Pholus_Scan p2
@@ -153,7 +155,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
conn.commit()
# Shrink DB
- mylog('verbose', ['[DBCLNP] Shrink Database'])
+ mylog('verbose', [f'[{pluginName}] Shrink Database'])
cursor.execute ("VACUUM;")
# Close the database connection
diff --git a/front/plugins/nslookup_scan/README.md b/front/plugins/nslookup_scan/README.md
new file mode 100755
index 00000000..b74a85f0
--- /dev/null
+++ b/front/plugins/nslookup_scan/README.md
@@ -0,0 +1,7 @@
+## Overview
+
+Plugin for device name discovery via the [nslookup](https://linux.die.net/man/1/nslookup) network utility.
+
+### Usage
+
+- Check the Settings page for details.
diff --git a/front/plugins/nslookup_scan/config.json b/front/plugins/nslookup_scan/config.json
new file mode 100755
index 00000000..c49a41cc
--- /dev/null
+++ b/front/plugins/nslookup_scan/config.json
@@ -0,0 +1,321 @@
+{
+ "code_name": "nslookup_scan",
+ "unique_prefix": "NSLOOKUP",
+ "plugin_type": "other",
+ "enabled": true,
+ "data_source": "script",
+ "show_ui": true,
+ "localized": ["display_name", "description", "icon"],
+ "display_name": [
+ {
+ "language_code": "en_us",
+ "string": "NSLOOKUP (Name discovery)"
+ }
+ ],
+ "icon": [
+ {
+ "language_code": "en_us",
+ "string": ""
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "A plugin to discover device names."
+ }
+ ],
+ "params" : [
+ {
+ "name" : "ips",
+ "type" : "sql",
+ "value" : "SELECT dev_LastIP from DEVICES order by dev_MAC",
+ "timeoutMultiplier" : true
+ }
+ ],
+ "settings": [
+ {
+ "function": "RUN",
+ "events": ["run"],
+ "type": "text.select",
+ "default_value":"on_new_device",
+ "options": ["disabled", "on_new_device", "once", "schedule", "always_after_scan"],
+ "localized": ["name", "description"],
+ "name" :[{
+ "language_code":"en_us",
+ "string" : "When to run"
+ },
+ {
+ "language_code":"es_es",
+ "string" : "Cuándo ejecutar"
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Wann laufen"
+ }],
+ "description": [{
+ "language_code":"en_us",
+ "string" : "When the plugin should be executed. If enabled this will execute the scan until there are no (unknown) or (name not found) devices. Setting this to on_new_device or a daily schedule is recommended."
+ }]
+ },
+ {
+ "function": "CMD",
+ "type": "readonly",
+ "default_value": "python3 /home/pi/pialert/front/plugins/nslookup_scan/nslookup.py",
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Command"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Comando"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Befehl"
+ }
+ ],
+ "description": [
+ {
+ "language_code": "en_us",
+ "string": "Command to run. This can not be changed"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Comando a ejecutar. Esto no se puede cambiar"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Befehl zum Ausführen. Dies kann nicht geändert werden"
+ }
+ ]
+ },
+ {
+ "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"
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Schedule"
+ }],
+ "description": [{
+ "language_code":"en_us",
+ "string" : "Only enabled if you select schedule in the NSLOOKUP_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 está habilitado si selecciona schedule en la configuración NSLOOKUP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE código> que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo."
+ },
+ {
+ "language_code":"de_de",
+ "string" : "Nur aktiviert, wenn Sie schedule in der NSLOOKUP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE ausgeführt. Code> den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht."
+ }]
+ },
+ {
+ "function": "RUN_TIMEOUT",
+ "type": "integer",
+ "default_value": 10,
+ "options": [],
+ "localized": ["name", "description"],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Run timeout"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Tiempo límite de ejecución"
+ },
+ {
+ "language_code": "de_de",
+ "string": "Zeitüberschreitung"
+ }
+ ],
+ "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."
+ },
+ {
+ "language_code": "de_de",
+ "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen."
+ }
+ ]
+ }
+ ],
+ "database_column_definitions":
+ [
+ {
+ "column": "Object_PrimaryID",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "device_name_mac",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "MAC"
+ },
+ {
+ "language_code": "es_es",
+ "string": "MAC"
+ }
+ ]
+ },
+ {
+ "column": "Object_SecondaryID",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "label",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "IP"
+ },
+ {
+ "language_code": "es_es",
+ "string": "IP"
+ }
+ ]
+ },
+ {
+ "column": "Watched_Value1",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "label",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Server"
+ }
+ ]
+ },
+ {
+ "column": "Watched_Value2",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "label",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Name"
+ }
+ ]
+ },
+ {
+ "column": "DateTimeCreated",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "label",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Created"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Creado"
+ }
+ ]
+ },
+ {
+ "column": "DateTimeChanged",
+ "css_classes": "col-sm-2",
+ "show": true,
+ "type": "label",
+ "default_value": "",
+ "options": [],
+ "localized": [
+ "name"
+ ],
+ "name": [
+ {
+ "language_code": "en_us",
+ "string": "Changed"
+ },
+ {
+ "language_code": "es_es",
+ "string": "Cambiado"
+ }
+ ]
+ },
+ {
+ "column": "Status",
+ "css_classes": "col-sm-1",
+ "show": true,
+ "type": "replace",
+ "default_value": "",
+ "options": [
+ {
+ "equals": "watched-not-changed",
+ "replacement": "