From 95a7dcc7fc672e1650727656f6fcbe77704519d9 Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Wed, 17 May 2023 12:55:34 +1000 Subject: [PATCH 1/6] undiscoverables initial version --- front/plugins/undiscoverables/config.json | 158 ++++++++++++++++++ .../plugins/undiscoverables/plugin_helper.py | 81 +++++++++ front/plugins/undiscoverables/script.py | 38 +++++ 3 files changed, 277 insertions(+) create mode 100644 front/plugins/undiscoverables/config.json create mode 100644 front/plugins/undiscoverables/plugin_helper.py create mode 100644 front/plugins/undiscoverables/script.py diff --git a/front/plugins/undiscoverables/config.json b/front/plugins/undiscoverables/config.json new file mode 100644 index 00000000..b997d1e6 --- /dev/null +++ b/front/plugins/undiscoverables/config.json @@ -0,0 +1,158 @@ +{ + "code_name": "undiscoverables", + "unique_prefix": "UNDIS", + "enabled": true, + "data_source": "python-script", + "localized": ["display_name", "description", "icon"], + + "display_name": [ + { + "language_code": "en_us", + "string": "Un-Discoverable Devices" + } + ], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "This plugin is to import undiscoverable devices from a file." + } + ], + + "settings": [ + { + "function": "RUN", + "type": "selecttext", + "default_value": "once", + "options": [ + "disabled", + "once", + "schedule", + "always_after_scan", + "on_new_device" + ], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "When to run" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Enable import of devices from a file. 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) or after you update your settings." + } + ] + }, + { + "function": "CMD", + "type": "text", + "default_value": "python3 /home/pi/pialert/front/plugins/undiscoverables/script.py", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Command" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Command to run" + } + ] + }, + { + "function": "RUN_SCHD", + "type": "text", + "default_value": "0 2 * * *", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Schedule" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Only enabled if you select schedule in the DHCPLSS_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." + } + ] + }, + { + "function": "RUN_TIMEOUT", + "type": "integer", + "default_value": 5, + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Run timeout" + }, + { + "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." + } + ] + }, + { + "function": "WATCH", + "type": "multiselect", + "default_value": ["Watched_Value1", "Watched_Value4"], + "options": [ + "Watched_Value1", + "Watched_Value2", + "Watched_Value3", + "Watched_Value4" + ], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Watched" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect. " + } + ] + }, + { + "function": "REPORT_ON", + "type": "multiselect", + "default_value": ["new", "watched-changed"], + "options": ["new", "watched-changed", "watched-not-changed"], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Report on" + } + ], + "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." + } + ] + } + ] +} diff --git a/front/plugins/undiscoverables/plugin_helper.py b/front/plugins/undiscoverables/plugin_helper.py new file mode 100644 index 00000000..31b46ae7 --- /dev/null +++ b/front/plugins/undiscoverables/plugin_helper.py @@ -0,0 +1,81 @@ + +from time import sleep, time, strftime +import sys +import pathlib + +# ------------------------------------------------------------------- +class Plugin_Object: + def __init__( + self, + primaryId="", + secondaryId="", + watched1="", + watched2="", + watched3="", + watched4="", + extra="", + foreignKey="" + ): + self.pluginPref = "" + self.primaryId = primaryId + self.secondaryId = secondaryId + self.created = strftime("%Y-%m-%d %H:%M:%S") + self.changed = "" + self.watched1 = watched1 + self.watched2 = watched2 + self.watched3 = watched3 + self.watched4 = watched4 + self.status = "" + self.extra = extra + self.userData = "" + self.foreignKey = foreignKey + + def write(self): + line = ("{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format( + self.primaryId, + self.secondaryId, + self.created, + self.watched1, + self.watched2, + self.watched3, + self.watched4, + self.extra, + self.foreignKey + ) + ) + return line + + + +class Plugin_Objects: + def __init__(self, result_file): + self.result_file = result_file + self.objects = [] + + def add_object ( self, primaryId="", + secondaryId="", + watched1="", + watched2="", + watched3="", + watched4="", + extra="", + foreignKey="" ): + + self.objects.append(Plugin_Object(primaryId, + secondaryId, + watched1, + watched2, + watched3, + watched4, + extra, + foreignKey) + ) + + + def write_result_file(self): + + with open(self.result_file, mode='w') as fp: + for obj in self.objects: + fp.write ( obj.write() ) + fp.close() + diff --git a/front/plugins/undiscoverables/script.py b/front/plugins/undiscoverables/script.py new file mode 100644 index 00000000..6737ce1d --- /dev/null +++ b/front/plugins/undiscoverables/script.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# Based on the work of https://github.com/leiweibau/Pi.Alert + +# python3 /home/pi/pialert/front/plugins/website_monitor/script.py urls=http://google.com,http://bing.com + +import sys +import pathlib + +from plugin_helper import Plugin_Objects, Plugin_Object + +sys.dont_write_bytecode = True + +curPath = str(pathlib.Path(__file__).parent.resolve()) +log_file = curPath + '/script.log' +result_file = curPath + '\last_result.log' + +FAKE_DEVICES = ["routerXX","hubZZ"] + + +def main(): + print("Hello") + + devices = Plugin_Objects( result_file ) + + + for fake_dev in FAKE_DEVICES: + devices.add_object(fake_dev, fake_dev, fake_dev, fake_dev, "", "", "", "") + + devices.write_result_file() + + return devices + + +#=============================================================================== +# BEGIN +#=============================================================================== +if __name__ == '__main__': + d = main() \ No newline at end of file From 6c8fc093afd12bc2a483c546ab3c54b3eb266909 Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Wed, 17 May 2023 13:05:50 +1000 Subject: [PATCH 2/6] update git ignore to ignore pycache --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index ea9c9e15..f908738e 100755 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ front/log/* front/plugins/**/*.log **/%40eaDir/ **/@eaDir/ + +__pycache__/ +*.py[cod] +*$py.class \ No newline at end of file From 07e839553672b7eaab405f71a29f680d3e7f9def Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Wed, 17 May 2023 13:45:21 +1000 Subject: [PATCH 3/6] file path fixed --- front/plugins/undiscoverables/plugin_helper.py | 2 +- front/plugins/undiscoverables/script.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/front/plugins/undiscoverables/plugin_helper.py b/front/plugins/undiscoverables/plugin_helper.py index 31b46ae7..68634623 100644 --- a/front/plugins/undiscoverables/plugin_helper.py +++ b/front/plugins/undiscoverables/plugin_helper.py @@ -73,7 +73,7 @@ class Plugin_Objects: def write_result_file(self): - + # print ("writing file: "+self.result_file) with open(self.result_file, mode='w') as fp: for obj in self.objects: fp.write ( obj.write() ) diff --git a/front/plugins/undiscoverables/script.py b/front/plugins/undiscoverables/script.py index 6737ce1d..fa51e221 100644 --- a/front/plugins/undiscoverables/script.py +++ b/front/plugins/undiscoverables/script.py @@ -6,13 +6,13 @@ import sys import pathlib -from plugin_helper import Plugin_Objects, Plugin_Object +from plugin_helper import Plugin_Objects sys.dont_write_bytecode = True curPath = str(pathlib.Path(__file__).parent.resolve()) log_file = curPath + '/script.log' -result_file = curPath + '\last_result.log' +result_file = curPath + '/last_result.log' FAKE_DEVICES = ["routerXX","hubZZ"] @@ -25,14 +25,17 @@ def main(): for fake_dev in FAKE_DEVICES: devices.add_object(fake_dev, fake_dev, fake_dev, fake_dev, "", "", "", "") + + #for obj in devices.objects: + # print(obj.write()) devices.write_result_file() - return devices + return 0 #=============================================================================== # BEGIN #=============================================================================== if __name__ == '__main__': - d = main() \ No newline at end of file + main() \ No newline at end of file From a0501d88ec7ac5b4542455fa45efca3c7cfb39c6 Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Wed, 17 May 2023 22:25:33 +1000 Subject: [PATCH 4/6] working version of UnDIS plugin --- db/pialert.db | Bin 180224 -> 0 bytes front/plugins/undiscoverables/config.json | 185 ++++++++++++++-------- front/plugins/undiscoverables/script.py | 40 ++--- 3 files changed, 144 insertions(+), 81 deletions(-) delete mode 100755 db/pialert.db diff --git a/db/pialert.db b/db/pialert.db deleted file mode 100755 index ff4e27315457b56f048e1ce792b7f6e37591bc93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180224 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 diff --git a/front/plugins/undiscoverables/config.json b/front/plugins/undiscoverables/config.json index b997d1e6..c1d9b509 100644 --- a/front/plugins/undiscoverables/config.json +++ b/front/plugins/undiscoverables/config.json @@ -3,6 +3,8 @@ "unique_prefix": "UNDIS", "enabled": true, "data_source": "python-script", + "mapped_to_table": "DHCP_Leases", + "localized": ["display_name", "description", "icon"], "display_name": [ @@ -23,37 +25,33 @@ "string": "This plugin is to import undiscoverable devices from a file." } ], + "params" : [ + { + "name" : "devices", + "type" : "setting", + "value" : "UNDIS_devices_to_import" + }], "settings": [ { - "function": "RUN", - "type": "selecttext", - "default_value": "once", - "options": [ - "disabled", - "once", - "schedule", - "always_after_scan", - "on_new_device" - ], + "function": "RUN", + "type": "selecttext", + "default_value":"disabled", + "options": ["disabled", "once", "always_after_scan"], "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "When to run" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Enable import of devices from a file. 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) or after you update your settings." - } - ] - }, + "name" :[{ + "language_code":"en_us", + "string" : "When to run" + }], + "description": [{ + "language_code":"en_us", + "string" : "When enabled, once is the preferred option. It runs at startup and after every save of the config here.
Changes will only show in the devices after the next scan!" + }] + }, { "function": "CMD", - "type": "text", - "default_value": "python3 /home/pi/pialert/front/plugins/undiscoverables/script.py", + "type": "readonly", + "default_value": "python3 /home/pi/pialert/front/plugins/undiscoverables/script.py devices={devices}", "options": [], "localized": ["name", "description"], "name": [ @@ -65,43 +63,21 @@ "description": [ { "language_code": "en_us", - "string": "Command to run" - } - ] - }, - { - "function": "RUN_SCHD", - "type": "text", - "default_value": "0 2 * * *", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Schedule" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Only enabled if you select schedule in the DHCPLSS_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." + "string": "Command to run. This can not be changed" } ] }, + { "function": "RUN_TIMEOUT", "type": "integer", - "default_value": 5, + "default_value": 10, "options": [], "localized": ["name", "description"], "name": [ { "language_code": "en_us", "string": "Run timeout" - }, - { - "language_code": "de_de", - "string": "Wartezeit" } ], "description": [ @@ -113,14 +89,9 @@ }, { "function": "WATCH", - "type": "multiselect", - "default_value": ["Watched_Value1", "Watched_Value4"], - "options": [ - "Watched_Value1", - "Watched_Value2", - "Watched_Value3", - "Watched_Value4" - ], + "type": "lable", + "default_value": [], + "options": [], "localized": ["name", "description"], "name": [ { @@ -131,14 +102,14 @@ "description": [ { "language_code": "en_us", - "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect.
  • Watched_Value1 is Active
  • Watched_Value2 is Hostname
  • Watched_Value3 is hardware
  • Watched_Value4 is State
" + "string": "Undiscoverable Devices can not change their status, no watch is enabled." } ] }, { "function": "REPORT_ON", - "type": "multiselect", - "default_value": ["new", "watched-changed"], + "type": "lable", + "default_value": [], "options": ["new", "watched-changed", "watched-not-changed"], "localized": ["name", "description"], "name": [ @@ -150,9 +121,97 @@ "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." + "string": "No notifications will be sent." } ] - } + }, + { + "function": "devices_to_import", + "type": "list", + "default_value":["dummy_router"], + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "UnDiscoverable Devices" + }], + "description": [{ + "language_code":"en_us", + "string" : "Devices to be added to the devices list." + }] + } + ], + + "database_column_definitions": + [ + { + "column": "Watched_Value1", + "mapped_to_column": "DHCP_Name", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Device Name" + }] + }, + { + "column": "Object_PrimaryID", + "mapped_to_column": "DHCP_MAC", + "css_classes": "col-sm-2", + "show": true, + "type": "devicemac", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "MAC address" + }] + }, + { + "column": "Object_SecondaryID", + "mapped_to_column": "DHCP_IP", + "css_classes": "col-sm-2", + "show": true, + "type": "deviceip", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "IP" + }] + } , + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Created" + }] + }, + { + "column": "DateTimeChanged", + "mapped_to_column": "DHCP_DateTime", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [], + "localized": ["name"], + "name":[{ + "language_code":"en_us", + "string" : "Changed" + }] + } ] } diff --git a/front/plugins/undiscoverables/script.py b/front/plugins/undiscoverables/script.py index fa51e221..93d38310 100644 --- a/front/plugins/undiscoverables/script.py +++ b/front/plugins/undiscoverables/script.py @@ -1,35 +1,39 @@ #!/usr/bin/env python -# Based on the work of https://github.com/leiweibau/Pi.Alert +# test script by running python script.py devices=test,dummy -# python3 /home/pi/pialert/front/plugins/website_monitor/script.py urls=http://google.com,http://bing.com - -import sys +import os import pathlib +import argparse from plugin_helper import Plugin_Objects -sys.dont_write_bytecode = True - curPath = str(pathlib.Path(__file__).parent.resolve()) -log_file = curPath + '/script.log' -result_file = curPath + '/last_result.log' +log_file = os.path.join(curPath , 'script.log') +result_file = os.path.join(curPath , 'last_result.log') -FAKE_DEVICES = ["routerXX","hubZZ"] def main(): - print("Hello") - devices = Plugin_Objects( result_file ) + parser = argparse.ArgumentParser(description='Import devices from dhcp.leases files') + parser.add_argument('devices', action="store", help="absolute dhcp.leases file paths to check separated by ','") + values = parser.parse_args() + + undis_devices = Plugin_Objects( result_file ) + if values.devices: + for fake_dev in values.devices.split('=')[1].split(','): + undis_devices.add_object( + primaryId=fake_dev, # MAC + secondaryId="0.0.0.0", # IP Address + watched1=fake_dev, # Device Name + watched2="", + watched3="", + watched4="UNDIS", # used as ScanMethod + extra="1", # used as dummy ScanCycle + foreignKey="") - for fake_dev in FAKE_DEVICES: - devices.add_object(fake_dev, fake_dev, fake_dev, fake_dev, "", "", "", "") - - #for obj in devices.objects: - # print(obj.write()) - - devices.write_result_file() + undis_devices.write_result_file() return 0 From 1474cf424b91a9444bbca9d9c2545e3a61806212 Mon Sep 17 00:00:00 2001 From: Data-Monkey Date: Thu, 18 May 2023 17:43:16 +1000 Subject: [PATCH 5/6] code and documentation tidied up --- front/plugins/undiscoverables/README.md | 20 +++++ front/plugins/undiscoverables/config.json | 2 +- .../plugins/undiscoverables/plugin_helper.py | 83 +++++++++++-------- front/plugins/undiscoverables/script.py | 34 ++++---- 4 files changed, 87 insertions(+), 52 deletions(-) create mode 100644 front/plugins/undiscoverables/README.md diff --git a/front/plugins/undiscoverables/README.md b/front/plugins/undiscoverables/README.md new file mode 100644 index 00000000..2c594243 --- /dev/null +++ b/front/plugins/undiscoverables/README.md @@ -0,0 +1,20 @@ +## Overview + +A plugin allowing for importing Un-Discoverable devices from the settings page. + + +### Usage + +- Go to settings and find Un-Discoverabe Devices in the list of plugins. +- Enable the plugin by changing the RUN parameter from disabled to `once` or `always_after_scan`. +- Add the name of your device to the list. (remove the sample entry first) +- SAVE +- wait for the next scan to finish + +#### Example: + + + +### Known Limitations + - Un-Discoverable Devices always show as offline. That is expected as they can not be discovered by Pi.Alert. + - All IPs are set to 0.0.0.0 therefore the "Random MAC" icon might show up. diff --git a/front/plugins/undiscoverables/config.json b/front/plugins/undiscoverables/config.json index c1d9b509..de03f76f 100644 --- a/front/plugins/undiscoverables/config.json +++ b/front/plugins/undiscoverables/config.json @@ -45,7 +45,7 @@ }], "description": [{ "language_code":"en_us", - "string" : "When enabled, once is the preferred option. It runs at startup and after every save of the config here.
Changes will only show in the devices after the next scan!" + "string" : "When enabled, \"once\" is the preferred option. It runs at startup and after every save of the config here.
Changes will only show in the devices after the next scan!" }] }, { diff --git a/front/plugins/undiscoverables/plugin_helper.py b/front/plugins/undiscoverables/plugin_helper.py index 68634623..e198f30a 100644 --- a/front/plugins/undiscoverables/plugin_helper.py +++ b/front/plugins/undiscoverables/plugin_helper.py @@ -1,10 +1,14 @@ - -from time import sleep, time, strftime -import sys -import pathlib +from time import strftime + # ------------------------------------------------------------------- class Plugin_Object: + """ + Plugin_Object class to manage one object introduced by the plugin + An object typically is a device but could also be a website or something + else that is monitored by the plugin. + """ + def __init__( self, primaryId="", @@ -14,7 +18,7 @@ class Plugin_Object: watched3="", watched4="", extra="", - foreignKey="" + foreignKey="", ): self.pluginPref = "" self.primaryId = primaryId @@ -29,53 +33,64 @@ class Plugin_Object: self.extra = extra self.userData = "" self.foreignKey = foreignKey - + def write(self): - line = ("{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format( - self.primaryId, - self.secondaryId, - self.created, - self.watched1, - self.watched2, - self.watched3, - self.watched4, - self.extra, - self.foreignKey - ) + """ + write the object details as a string in the + format required to write the result file + """ + line = "{}|{}|{}|{}|{}|{}|{}|{}|{}\n".format( + self.primaryId, + self.secondaryId, + self.created, + self.watched1, + self.watched2, + self.watched3, + self.watched4, + self.extra, + self.foreignKey, ) return line - class Plugin_Objects: + """ + Plugin_Objects is the class that manages and holds all the objects created by the plugin. + It contains a list of Plugin_Object instances. + And can write the required result file. + """ + def __init__(self, result_file): - self.result_file = result_file + self.result_file = result_file self.objects = [] - def add_object ( self, primaryId="", + def add_object( + self, + primaryId="", secondaryId="", watched1="", watched2="", watched3="", watched4="", extra="", - foreignKey="" ): - - self.objects.append(Plugin_Object(primaryId, - secondaryId, - watched1, - watched2, - watched3, - watched4, - extra, - foreignKey) + foreignKey="", + ): + self.objects.append( + Plugin_Object( + primaryId, + secondaryId, + watched1, + watched2, + watched3, + watched4, + extra, + foreignKey, + ) ) - def write_result_file(self): # print ("writing file: "+self.result_file) - with open(self.result_file, mode='w') as fp: + with open(self.result_file, mode="w") as fp: for obj in self.objects: - fp.write ( obj.write() ) + fp.write(obj.write()) fp.close() - diff --git a/front/plugins/undiscoverables/script.py b/front/plugins/undiscoverables/script.py index 93d38310..7f17554d 100644 --- a/front/plugins/undiscoverables/script.py +++ b/front/plugins/undiscoverables/script.py @@ -7,36 +7,36 @@ import argparse from plugin_helper import Plugin_Objects -curPath = str(pathlib.Path(__file__).parent.resolve()) -log_file = os.path.join(curPath , 'script.log') -result_file = os.path.join(curPath , 'last_result.log') +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') def main(): - parser = argparse.ArgumentParser(description='Import devices from dhcp.leases files') - parser.add_argument('devices', action="store", help="absolute dhcp.leases file paths to check separated by ','") - values = parser.parse_args() + # the script expects a parameter in the format of devices=device1,device2,... + parser = argparse.ArgumentParser(description='Import devices from settings') + parser.add_argument('devices', action="store", help="list of device names separated by ','") + values = parser.parse_args() - undis_devices = Plugin_Objects( result_file ) - - if values.devices: + UNDIS_devices = Plugin_Objects( RESULT_FILE ) + + if values.devices: for fake_dev in values.devices.split('=')[1].split(','): - undis_devices.add_object( - primaryId=fake_dev, # MAC - secondaryId="0.0.0.0", # IP Address + UNDIS_devices.add_object( + primaryId=fake_dev, # MAC (Device Name) + secondaryId="0.0.0.0", # IP Address (always 0.0.0.0) watched1=fake_dev, # Device Name watched2="", watched3="", - watched4="UNDIS", # used as ScanMethod - extra="1", # used as dummy ScanCycle + watched4="", + extra="", foreignKey="") - undis_devices.write_result_file() + UNDIS_devices.write_result_file() - return 0 - + return 0 #=============================================================================== # BEGIN From 4027970975e0eb970527365d6ed006390fb161b6 Mon Sep 17 00:00:00 2001 From: Roland Beck <7224371+Data-Monkey@users.noreply.github.com> Date: Thu, 18 May 2023 17:57:48 +1000 Subject: [PATCH 6/6] Update README.md added some pictures --- front/plugins/undiscoverables/README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/front/plugins/undiscoverables/README.md b/front/plugins/undiscoverables/README.md index 2c594243..622c5306 100644 --- a/front/plugins/undiscoverables/README.md +++ b/front/plugins/undiscoverables/README.md @@ -1,7 +1,8 @@ ## Overview A plugin allowing for importing Un-Discoverable devices from the settings page. - +The main usecase is to add dumb network gear like unmanaged hubs and switches to the network view. +There might be other usecases, please let me know. ### Usage @@ -11,9 +12,15 @@ A plugin allowing for importing Un-Discoverable devices from the settings page. - SAVE - wait for the next scan to finish -#### Example: +#### Examples: +Settings: +![settings](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/52883307-19a5-4602-b13a-9825461f6cc4) +resulting in these devices: +![devices](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/9f7659e7-75a8-4ae9-9f5f-781bdbcbc949) +Allowing Un-Discoverable devices like hubs, switches or APs to be added to the network view. +![network](https://github.com/Data-Monkey/Pi.Alert/assets/7224371/b5ccc3b3-f5fd-4f5b-b0f0-e4e637c6da33) ### Known Limitations - Un-Discoverable Devices always show as offline. That is expected as they can not be discovered by Pi.Alert.