mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Compare commits
7 Commits
3e35f08d6c
...
a69f72fd3d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a69f72fd3d | ||
|
|
df40b5caf9 | ||
|
|
54b6b1d408 | ||
|
|
d79acc7bad | ||
|
|
57d8db771a | ||
|
|
43759b6b7d | ||
|
|
3305828947 |
@@ -673,7 +673,9 @@
|
||||
|
||||
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
||||
|
||||
(port == "" || port == 0 ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
|
||||
(port == "" || port == 0 || port == 'None' ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
|
||||
|
||||
portHtml = (port == "" || port == 0 || port == 'None' ) ? "" : port
|
||||
|
||||
// Build HTML for individual nodes in the network diagram
|
||||
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
|
||||
@@ -682,7 +684,7 @@
|
||||
</div>` : "";
|
||||
devicePort = `<div class="netPort"
|
||||
style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em">
|
||||
${port}</div>
|
||||
${portHtml}</div>
|
||||
<div class="portBckgIcon"
|
||||
style="margin-left:-${emSize*sizeCoefficient}em;">
|
||||
${portBckgIcon}
|
||||
|
||||
@@ -16,7 +16,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath, fullDbPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -19,7 +19,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, check_IP_format
|
||||
from helper import timeNowTZ, get_setting_value, check_IP_format
|
||||
from const import logPath, applicationPath, fullDbPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -15,6 +15,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, handleEmpty, is_mac
|
||||
from logger import mylog
|
||||
from dhcp_leases import DhcpLeases
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Objects, Plugin_Object
|
||||
from logger import mylog
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Objects
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -6,6 +6,8 @@ __version__ = "0.3" # split devices API calls to allow multithreading but had t
|
||||
__version__ = "0.6" # found issue with multithreading - my omada calls redirect stdout which gets clubbered by normal stdout... not sure how to fix for now...
|
||||
__version__ = "0.7" # avoid updating omada sdn client name when it is the MAC, and naxname is also the same MAC...
|
||||
__version__ = "1.0" # fixed the timzone mylog issue by resetting the tz value at the begining of the script... I suspect it doesn't inherit the tz from the main.
|
||||
__version__ = "1.1" # added logic to handle gracefully a failure of omada devices so it won't try to populate uplinks on non-existent switches and AP.
|
||||
|
||||
|
||||
# query OMADA SDN to populate NetAlertX witch omada switches, access points, clients.
|
||||
# try to identify and populate their connections by switch/accesspoints and ports/SSID
|
||||
@@ -454,7 +456,8 @@ def get_device_data(omada_clients_output,switches_and_aps,device_handler):
|
||||
# step4, let's go recursively through switches other links to mark update their uplinks
|
||||
# and pray it ends one day...
|
||||
#
|
||||
add_uplink(default_router_mac,first_switch, device_data_bymac,sadevices_linksbymac,port_byswitchmac_byclientmac)
|
||||
if len(sadevices) > 0:
|
||||
add_uplink(default_router_mac,first_switch, device_data_bymac,sadevices_linksbymac,port_byswitchmac_byclientmac)
|
||||
return device_data_bymac.values()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
238
front/plugins/omada_sdn_imp/testre.py
Normal file
238
front/plugins/omada_sdn_imp/testre.py
Normal file
@@ -0,0 +1,238 @@
|
||||
import re
|
||||
|
||||
""""
|
||||
how to rebuild and re-run...
|
||||
|
||||
savefolder=~/naxdev/NetAlertX.v7
|
||||
cd ~/naxdev
|
||||
mv NetAlertX $savefolder
|
||||
gh repo clone FlyingToto/NetAlertX
|
||||
cd NetAlertX
|
||||
ln -s ../docker-compose.yml.ffsb42 .
|
||||
ln -s ../.env.omada.ffsb42 .
|
||||
cd front/plugins/omada_sdn_imp/
|
||||
cp -p $savefoder/front/plugins/omada_sdn_imp/omada_sdn.py* .
|
||||
cp -p $savefoder/front/plugins/omada_sdn_imp/README.md .
|
||||
cp -p $savefoder/front/plugins/omada_sdn_imp/omada_account_sample.png .
|
||||
cp -p $savefoder/front/plugins/omada_sdn_imp/testre.py .
|
||||
#cp -p $savefoder/front/plugins/omada_sdn_imp/config.json config.json.v6
|
||||
cd ~/naxdev/NetAlertX
|
||||
sudo docker-compose --env-file .env.omada.ffsb42 -f ./docker-compose.yml.ffsb42 up
|
||||
|
||||
to gather data for Boris:
|
||||
today=$(date +%Y_%m_%d__%H_%M)
|
||||
mkdir /drives/c/temp/4boris/$today
|
||||
cd /drives/c/temp/4boris/$today
|
||||
scp hal:~/naxdev/logs/app.log .
|
||||
scp hal:~/naxdev/NetAlertX/front/plugins/omada_sdn_imp/* .
|
||||
gzip -c app.log > app_$today.log.gz
|
||||
|
||||
|
||||
scp hal:~/naxdev/NetAlertX/front/plugins/omada_sdn_imp/omada_sdn.py /drives/c/temp/4boris/
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
def extract_mac_addresses(text):
|
||||
mac_pattern = r"([0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2})"
|
||||
#mac_pattern = r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})'
|
||||
#r"(([0-9A-F]{2}-){5}[0-9A-F]{2})"
|
||||
#r"([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})"
|
||||
#r"([0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2})"
|
||||
mac_addresses = re.findall(mac_pattern, text)
|
||||
return ["".join(parts) for parts in mac_addresses]
|
||||
|
||||
# Example usage:
|
||||
foo = """
|
||||
Name: office
|
||||
Address: 0C-80-63-69-C4-D1 (192.168.0.5)
|
||||
Status: CONNECTED (CONNECTED)
|
||||
Ports: 28
|
||||
Supports PoE: False
|
||||
Model: T1600G-28TS v3.0
|
||||
LED Setting: SITE_SETTINGS
|
||||
Uptime: 5day(s) 22h 39m 6s
|
||||
Uplink switch: D8-07-B6-71-FF-7F office24
|
||||
Downlink devices:
|
||||
- 40-AE-30-A5-A7-50 ompapaoffice
|
||||
- B0-95-75-46-0C-39 pantry12
|
||||
"""
|
||||
|
||||
mac_list = extract_mac_addresses(foo)
|
||||
print("mac list",mac_list)
|
||||
# ['0C-80-63-69-C4-D1', 'D8-07-B6-71-FF-7F', '40-AE-30-A5-A7-50', 'B0-95-75-46-0C-39']
|
||||
# ['C4-:D1', 'FF-:7F', 'A7-:50', '0C-:39']
|
||||
|
||||
linked_switches_and_ports_by_mac = {}
|
||||
|
||||
|
||||
foo = """"
|
||||
something
|
||||
some BOB12
|
||||
blah BOB23
|
||||
--- BEGIN ---
|
||||
something else BOB12
|
||||
blah BOB23
|
||||
--- END ---
|
||||
"""
|
||||
def extract_BOB_patterns(foo):
|
||||
pattern = r"BOB\d{2}(?=.*BEGIN)"
|
||||
matches = re.findall(pattern, foo, re.DOTALL)
|
||||
return matches
|
||||
|
||||
BOBresult = extract_BOB_patterns(foo)
|
||||
print("BOB:",BOBresult) # Output: ['BOB12', 'BOB23']
|
||||
|
||||
|
||||
#0C-80-63-69-C4-D1
|
||||
clientmac_by_switchmac_by_switchportSSID = {}
|
||||
switch_mac_and_ports_by_clientmac = {}
|
||||
|
||||
def extract_uplinks_mac_and_ports(tplink_device_dump):
|
||||
mac_switches = []
|
||||
mac_pattern = r"([0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2}[:-][0-9A-Fa-f]{2})(?=.*BEGIN)"
|
||||
mac_addresses = re.findall(mac_pattern, tplink_device_dump,re.DOTALL)
|
||||
mac_switches = ["".join(parts) for parts in mac_addresses]
|
||||
print(" mac_switches1=",mac_switches)
|
||||
mymac = mac_switches[0]
|
||||
mylinks = mac_switches[1:]
|
||||
for mylink in mylinks:
|
||||
port_pattern = r"(?=\{.*\"port\"\: )([0-9]+)(?=.*"+re.escape(mylink)+r")"
|
||||
port_pattern = r"(?:{/s\"port\"\: )([0-9]+)(?:[!\}].*"+re.escape(mylink)+r")"
|
||||
#port_pattern = rf"{{.*?{found_mac}.*?port\s*:\s*(\d+).*?}}"
|
||||
#port_pattern = rf"{{.*?.*?port\s*:\s*(\d+)[!\\}]*{mylink}?}}"
|
||||
port_pattern = r"(?:\{[!\}]port/s:/s)([0-9]+\,)(?:[!\}]*"+re.escape(mylink)+r"[!\{]*\})"
|
||||
#port_pattern = r"(?:\{.*\"port\"\: )([0-9]+)(?=.*"+re.escape(mylink)+r")"
|
||||
port_pattern = r"(?:{[^}]*\"port\"\: )([0-9]+)(?=[^}]*"+re.escape(mylink)+r")"
|
||||
|
||||
myport = re.findall(port_pattern, tplink_device_dump,re.DOTALL)
|
||||
print("myswitch=",mymac, "- link_switch=", mylink, "myport=", myport)
|
||||
return(0)
|
||||
|
||||
|
||||
'''
|
||||
with open('/tmp/switch.bigroom.dump.json', 'r') as file:
|
||||
foo3 = file_content = file.read()
|
||||
print("bigroom", end="")
|
||||
extract_uplinks_mac_and_ports(foo3)
|
||||
with open('/tmp/switch.office.dump.json', 'r') as file:
|
||||
foo4 = file_content = file.read()
|
||||
print("office", end="")
|
||||
extract_uplinks_mac_and_ports(foo4)
|
||||
'''
|
||||
|
||||
import netifaces
|
||||
gw = netifaces.gateways()
|
||||
print(gw['default'][netifaces.AF_INET][0])
|
||||
|
||||
|
||||
d = {'a': ['0', 'Arthur'], 'b': ['foo', 'Belling']}
|
||||
|
||||
print(d.items())
|
||||
print(d.keys())
|
||||
print(d.values())
|
||||
|
||||
|
||||
foo = 2
|
||||
#while foo > 0:
|
||||
# foo = 'toto'
|
||||
print("foo is ",foo)
|
||||
|
||||
if foo in ( 'bar', '', 'null'):
|
||||
print("foo is bar")
|
||||
else:
|
||||
print("foo is not bar")
|
||||
|
||||
foo='192-168-0-150.local'
|
||||
bar = foo.split('.')[0]
|
||||
print("bar=",bar,"-")
|
||||
bar2 = 'toto'
|
||||
print("bar2=",bar2,"-")
|
||||
|
||||
|
||||
|
||||
import concurrent.futures
|
||||
import time
|
||||
import random
|
||||
|
||||
def phello(arg):
|
||||
print('running phell',arg)
|
||||
delay = random.uniform(0, 6)
|
||||
time.sleep(delay)
|
||||
return f"parallel hello : {arg}", delay
|
||||
|
||||
def testparalel():
|
||||
arguments = ["Alice", "Bob", "Charlie", "David"]
|
||||
results = {}
|
||||
results2 = {}
|
||||
para = 10
|
||||
|
||||
# Using ThreadPoolExecutor for parallel execution
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=para) as executor:
|
||||
# Submit tasks to the executor
|
||||
future_to_arg = {executor.submit(phello, arg): arg for arg in arguments}
|
||||
|
||||
# Wait for all futures to complete
|
||||
done, _ = concurrent.futures.wait(future_to_arg)
|
||||
|
||||
# Retrieve results
|
||||
for future in done:
|
||||
arg = future_to_arg[future]
|
||||
try:
|
||||
result, result2 = future.result()
|
||||
results[arg] = result
|
||||
results2[arg] = result2
|
||||
except Exception as exc:
|
||||
print(f"{arg} generated an exception: {exc}")
|
||||
|
||||
# Print results after all threads have completed
|
||||
print("All threads completed. Results:")
|
||||
for arg, result in results.items():
|
||||
print(f"arg:{arg}, result={results[arg]}, result2={results2[arg]}")
|
||||
|
||||
|
||||
#testparalel()
|
||||
|
||||
|
||||
|
||||
import netifaces
|
||||
import ipaddress
|
||||
|
||||
def get_interfaces_and_subnets():
|
||||
result = []
|
||||
for interface in netifaces.interfaces():
|
||||
addrs = netifaces.ifaddresses(interface)
|
||||
if netifaces.AF_INET in addrs:
|
||||
for addr in addrs[netifaces.AF_INET]:
|
||||
ip = addr['addr']
|
||||
mask = addr['netmask']
|
||||
try:
|
||||
network = ipaddress.IPv4Network(f"{ip}/{mask}", strict=False)
|
||||
result.append((interface, str(network)))
|
||||
except ValueError:
|
||||
pass
|
||||
return result
|
||||
|
||||
# Example usage:
|
||||
interfaces_and_subnets = get_interfaces_and_subnets()
|
||||
for interface, subnet in interfaces_and_subnets:
|
||||
print(f"interface={interface}, subnet={subnet}")
|
||||
|
||||
|
||||
'''
|
||||
interface=lo, subnet=127.0.0.0/8
|
||||
interface=enp6s0, subnet=192.168.0.0/24
|
||||
interface=br-ba0070d71f2a, subnet=172.16.0.16/29
|
||||
interface=br-bc4a4c4e0f93, subnet=172.16.0.40/29
|
||||
interface=br-e043e0ae9c8c, subnet=172.16.0.72/29
|
||||
interface=br-6acc3945cfba, subnet=172.16.0.48/29
|
||||
interface=br-6f931807e709, subnet=172.16.0.80/29
|
||||
interface=docker0, subnet=172.17.0.0/16
|
||||
interface=br-9ce2cb7c38c3, subnet=172.16.0.24/29
|
||||
interface=br-eec81501f666, subnet=172.16.0.32/29
|
||||
interface=br-1064712a4791, subnet=172.16.0.56/29
|
||||
interface=br-a93ebdba2a28, subnet=172.16.0.8/29
|
||||
interface=br-d8fa7a3015e2, subnet=172.16.0.64/29
|
||||
interface=br-e7cdd041d3d3, subnet=172.16.0.0/29
|
||||
'''
|
||||
@@ -16,7 +16,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from logger import mylog
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -13,7 +13,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64, handleEmpty, normalize_mac
|
||||
from logger import mylog
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -13,7 +13,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
@@ -21,6 +21,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects
|
||||
from logger import mylog
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64, handleEmpty
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from const import logPath, applicationPath, fullDbPath
|
||||
from device import query_MAC_vendor
|
||||
import conf
|
||||
|
||||
@@ -15,6 +15,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
from plugin_helper import Plugin_Objects
|
||||
from datetime import datetime
|
||||
from const import logPath
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
import conf
|
||||
from pytz import timezone
|
||||
|
||||
|
||||
274
server/device.py
274
server/device.py
@@ -171,40 +171,48 @@ def create_new_devices (db):
|
||||
mylog('debug','[New Devices] 2 Create devices')
|
||||
|
||||
# default New Device values preparation
|
||||
newDevColumns = """dev_AlertEvents,
|
||||
dev_AlertDeviceDown,
|
||||
dev_PresentLastScan,
|
||||
dev_Archived,
|
||||
dev_NewDevice,
|
||||
dev_SkipRepeated,
|
||||
dev_ScanCycle,
|
||||
dev_Owner,
|
||||
dev_Favorite,
|
||||
dev_Group,
|
||||
dev_Comments,
|
||||
dev_LogEvents,
|
||||
dev_Location,
|
||||
dev_Icon"""
|
||||
newDevColumns = """dev_AlertEvents,
|
||||
dev_AlertDeviceDown,
|
||||
dev_PresentLastScan,
|
||||
dev_Archived,
|
||||
dev_NewDevice,
|
||||
dev_SkipRepeated,
|
||||
dev_ScanCycle,
|
||||
dev_Owner,
|
||||
dev_Favorite,
|
||||
dev_Group,
|
||||
dev_Comments,
|
||||
dev_LogEvents,
|
||||
dev_Location"""
|
||||
|
||||
newDevDefaults = f"""{get_setting_value('NEWDEV_dev_AlertEvents')},
|
||||
{get_setting_value('NEWDEV_dev_AlertDeviceDown')},
|
||||
{get_setting_value('NEWDEV_dev_PresentLastScan')},
|
||||
{get_setting_value('NEWDEV_dev_Archived')},
|
||||
{get_setting_value('NEWDEV_dev_NewDevice')},
|
||||
{get_setting_value('NEWDEV_dev_SkipRepeated')},
|
||||
{get_setting_value('NEWDEV_dev_ScanCycle')},
|
||||
'{get_setting_value('NEWDEV_dev_Owner')}',
|
||||
{get_setting_value('NEWDEV_dev_Favorite')},
|
||||
'{get_setting_value('NEWDEV_dev_Group')}',
|
||||
'{get_setting_value('NEWDEV_dev_Comments')}',
|
||||
{get_setting_value('NEWDEV_dev_LogEvents')},
|
||||
'{get_setting_value('NEWDEV_dev_Location')}',
|
||||
'{get_setting_value('NEWDEV_dev_Icon')}'
|
||||
"""
|
||||
newDevDefaults = f"""{get_setting_value('NEWDEV_dev_AlertEvents')},
|
||||
{get_setting_value('NEWDEV_dev_AlertDeviceDown')},
|
||||
{get_setting_value('NEWDEV_dev_PresentLastScan')},
|
||||
{get_setting_value('NEWDEV_dev_Archived')},
|
||||
{get_setting_value('NEWDEV_dev_NewDevice')},
|
||||
{get_setting_value('NEWDEV_dev_SkipRepeated')},
|
||||
{get_setting_value('NEWDEV_dev_ScanCycle')},
|
||||
'{get_setting_value('NEWDEV_dev_Owner')}',
|
||||
{get_setting_value('NEWDEV_dev_Favorite')},
|
||||
'{get_setting_value('NEWDEV_dev_Group')}',
|
||||
'{get_setting_value('NEWDEV_dev_Comments')}',
|
||||
{get_setting_value('NEWDEV_dev_LogEvents')},
|
||||
'{get_setting_value('NEWDEV_dev_Location')}'"""
|
||||
|
||||
# Bulk-inserting devices from the CurrentScan table as new devices in the table Devices ...
|
||||
# ... with new device defaults and ignoring specidfied IPs and MACs)
|
||||
sqlQuery = f"""INSERT OR IGNORE INTO Devices
|
||||
# Fetch data from CurrentScan
|
||||
current_scan_data = sql.execute("SELECT cur_MAC, cur_Name, cur_Vendor, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type FROM CurrentScan").fetchall()
|
||||
|
||||
for row in current_scan_data:
|
||||
cur_MAC, cur_Name, cur_Vendor, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type = row
|
||||
|
||||
# Handle NoneType
|
||||
cur_Name = cur_Name.strip() if cur_Name else '(unknown)'
|
||||
cur_Type = cur_Type.strip() if cur_Type else get_setting_value("NEWDEV_dev_DeviceType")
|
||||
cur_NetworkNodeMAC = cur_NetworkNodeMAC.strip() if cur_NetworkNodeMAC else ''
|
||||
cur_NetworkNodeMAC = cur_NetworkNodeMAC if cur_NetworkNodeMAC and cur_MAC != "Internet" else (get_setting_value("NEWDEV_dev_Network_Node_MAC_ADDR") if cur_MAC != "Internet" else "null")
|
||||
|
||||
# Preparing the individual insert statement
|
||||
sqlQuery = f"""INSERT OR IGNORE INTO Devices
|
||||
(
|
||||
dev_MAC,
|
||||
dev_name,
|
||||
@@ -221,44 +229,28 @@ def create_new_devices (db):
|
||||
dev_DeviceType,
|
||||
{newDevColumns}
|
||||
)
|
||||
SELECT
|
||||
cur_MAC,
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_Name)) > 0 THEN cur_Name ELSE '(unknown)'
|
||||
END,
|
||||
cur_Vendor,
|
||||
cur_IP,
|
||||
VALUES
|
||||
(
|
||||
'{cur_MAC}',
|
||||
'{cur_Name}',
|
||||
'{cur_Vendor}',
|
||||
'{cur_IP}',
|
||||
?,
|
||||
?,
|
||||
cur_SyncHubNodeName,
|
||||
{sql_generateGuid},
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_NetworkNodeMAC)) > 0
|
||||
AND cur_MAC != 'Internet'
|
||||
THEN cur_NetworkNodeMAC
|
||||
ELSE
|
||||
CASE
|
||||
WHEN cur_MAC = 'Internet'
|
||||
THEN 'null'
|
||||
ELSE '{get_setting_value('NEWDEV_dev_Network_Node_MAC_ADDR')}'
|
||||
END
|
||||
END,
|
||||
cur_PORT,
|
||||
cur_NetworkSite,
|
||||
cur_SSID,
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(cur_Type)) > 0 THEN cur_Type ELSE '{get_setting_value('NEWDEV_dev_DeviceType')}'
|
||||
END,
|
||||
'{cur_SyncHubNodeName}',
|
||||
{sql_generateGuid},
|
||||
'{cur_NetworkNodeMAC}',
|
||||
'{cur_PORT}',
|
||||
'{cur_NetworkSite}',
|
||||
'{cur_SSID}',
|
||||
'{cur_Type}',
|
||||
{newDevDefaults}
|
||||
FROM CurrentScan
|
||||
WHERE 1=1
|
||||
{list_to_where('OR', 'cur_MAC', 'NOT LIKE', get_setting_value('NEWDEV_ignored_MACs'))}
|
||||
{list_to_where('OR', 'cur_IP', 'NOT LIKE', get_setting_value('NEWDEV_ignored_IPs'))}
|
||||
"""
|
||||
)"""
|
||||
|
||||
mylog('debug',f'[New Devices] Create devices SQL: {sqlQuery}')
|
||||
mylog('trace', f'[New Devices] Create device SQL: {sqlQuery}')
|
||||
|
||||
sql.execute(sqlQuery, (startTime, startTime))
|
||||
|
||||
sql.execute (sqlQuery, (startTime, startTime) )
|
||||
|
||||
mylog('debug','[New Devices] New Devices end')
|
||||
db.commitDB()
|
||||
@@ -410,6 +402,7 @@ def update_devices_data_from_scan (db):
|
||||
AND cur_Name <> ''
|
||||
) """)
|
||||
|
||||
# Update VENDORS
|
||||
recordsToUpdate = []
|
||||
query = """SELECT * FROM Devices
|
||||
WHERE dev_Vendor = '(unknown)' OR dev_Vendor =''
|
||||
@@ -420,8 +413,40 @@ def update_devices_data_from_scan (db):
|
||||
if vendor != -1 and vendor != -2 :
|
||||
recordsToUpdate.append ([vendor, device['dev_MAC']])
|
||||
|
||||
sql.executemany ("UPDATE Devices SET dev_Vendor = ? WHERE dev_MAC = ? ",
|
||||
recordsToUpdate )
|
||||
if len(recordsToUpdate) > 0:
|
||||
sql.executemany ("UPDATE Devices SET dev_Vendor = ? WHERE dev_MAC = ? ", recordsToUpdate )
|
||||
|
||||
# Guess ICONS
|
||||
recordsToUpdate = []
|
||||
query = """SELECT * FROM Devices
|
||||
WHERE dev_Icon in ('', 'null')
|
||||
OR dev_Icon IS NULL"""
|
||||
default_icon = get_setting_value('NEWDEV_dev_Icon')
|
||||
|
||||
for device in sql.execute (query) :
|
||||
# Conditional logic for dev_Icon guessing
|
||||
dev_Icon = guess_icon(device['dev_Vendor'], device['dev_MAC'], device['dev_LastIP'], device['dev_Name'], default_icon)
|
||||
|
||||
recordsToUpdate.append ([dev_Icon, device['dev_MAC']])
|
||||
|
||||
if len(recordsToUpdate) > 0:
|
||||
sql.executemany ("UPDATE Devices SET dev_Icon = ? WHERE dev_MAC = ? ", recordsToUpdate )
|
||||
|
||||
# Guess Type
|
||||
recordsToUpdate = []
|
||||
query = """SELECT * FROM Devices
|
||||
WHERE dev_DeviceType in ('', 'null')
|
||||
OR dev_DeviceType IS NULL"""
|
||||
default_type = get_setting_value('NEWDEV_dev_DeviceType')
|
||||
|
||||
for device in sql.execute (query) :
|
||||
# Conditional logic for dev_Icon guessing
|
||||
dev_DeviceType = guess_type(device['dev_Vendor'], device['dev_MAC'], device['dev_LastIP'], device['dev_Name'], default_type)
|
||||
|
||||
recordsToUpdate.append ([dev_DeviceType, device['dev_MAC']])
|
||||
|
||||
if len(recordsToUpdate) > 0:
|
||||
sql.executemany ("UPDATE Devices SET dev_DeviceType = ? WHERE dev_MAC = ? ", recordsToUpdate )
|
||||
|
||||
|
||||
mylog('debug','[Update Devices] Update devices end')
|
||||
@@ -582,3 +607,118 @@ def query_MAC_vendor (pMAC):
|
||||
mylog('none', [f"[Vendor Check] ⚠ ERROR: Vendors file {vendorsPath} not found."])
|
||||
return -1
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Icons
|
||||
#===============================================================================
|
||||
#-------------------------------------------------------------------------------
|
||||
# Base64 encoded HTML string for FontAwesome icons
|
||||
icons = {
|
||||
"globe": "PGkgY2xhc3M9ImZhcyBmYS1nbG9iZSI+PC9pPg==", # globe icon
|
||||
"phone": "PGkgY2xhc3M9ImZhcyBmYS1tb2JpbGUtYWx0Ij48L2k+",
|
||||
"laptop": "PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==",
|
||||
"printer": "PGkgY2xhc3M9ImZhIGZhLXByaW50ZXIiPjwvaT4=",
|
||||
"router": "PGkgY2xhc3M9ImZhcyBmYS1yYW5kb20iPjwvaT4=",
|
||||
"tv": "PGkgY2xhc3M9ImZhIGZhLXR2Ij48L2k+",
|
||||
"desktop": "PGkgY2xhc3M9ImZhIGZhLWRlc2t0b3AiPjwvaT4=",
|
||||
"tablet": "PGkgY2xhc3M9ImZhIGZhLXRhYmxldCI+PC9pPg==",
|
||||
"watch": "PGkgY2xhc3M9ImZhIGZhLXdhbmNoIj48L2k+",
|
||||
"camera": "PGkgY2xhc3M9ImZhIGZhLWNhbWVyYSI+PC9pPg==",
|
||||
"home": "PGkgY2xhc3M9ImZhIGZhLWhvbWUiPjwvaT4=",
|
||||
"apple": "PGkgY2xhc3M9ImZhYiBmYS1hcHBsZSI+PC9pPg==",
|
||||
"ethernet": "PGkgY2xhc3M9ImZhcyBmYS1ldGhlcm5ldCI+PC9pPg==",
|
||||
"google": "PGkgY2xhc3M9ImZhYiBmYS1nb29nbGUiPjwvaT4=",
|
||||
"raspberry": "PGkgY2xhc3M9ImZhYiBmYS1yYXNwYmVycnktcGkiPjwvaT4=",
|
||||
"microchip": "PGkgY2xhc3M9ImZhcyBmYS1taWNyb2NoaXAiPjwvaT4="
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Guess device icon
|
||||
def guess_icon(vendor, mac, ip, name, default):
|
||||
result = default
|
||||
mac = mac.upper()
|
||||
vendor = vendor.lower()
|
||||
name = name.lower()
|
||||
|
||||
# Guess icon based on vendor
|
||||
if any(brand in vendor for brand in {"samsung", "motorola"}):
|
||||
result = icons.get("phone")
|
||||
elif "dell" in vendor:
|
||||
result = icons.get("laptop")
|
||||
elif "hp" in vendor:
|
||||
result = icons.get("printer")
|
||||
elif "cisco" in vendor:
|
||||
result = icons.get("router")
|
||||
elif "lg" in vendor:
|
||||
result = icons.get("tv")
|
||||
elif "raspberry" in vendor:
|
||||
result = icons.get("raspberry")
|
||||
elif "apple" in vendor:
|
||||
result = icons.get("apple")
|
||||
elif "google" in vendor:
|
||||
result = icons.get("google")
|
||||
elif "ubiquiti" in vendor:
|
||||
result = icons.get("router")
|
||||
elif any(brand in vendor for brand in {"espressif"}):
|
||||
result = icons.get("microchip")
|
||||
|
||||
# Guess icon based on MAC address patterns
|
||||
elif mac == "INTERNET": # Apple
|
||||
result = icons.get("globe")
|
||||
elif mac.startswith("00:1A:79"): # Apple
|
||||
result = icons.get("apple")
|
||||
elif mac.startswith("B0:BE:83"): # Apple
|
||||
result = icons.get("apple")
|
||||
elif mac.startswith("00:1B:63"): # Sony
|
||||
result = icons.get("tablet")
|
||||
elif mac.startswith("74:AC:B9"): # Unifi
|
||||
result = icons.get("ethernet")
|
||||
|
||||
|
||||
# Guess icon based on name
|
||||
elif 'google' in name:
|
||||
result = icons.get("google")
|
||||
elif 'desktop' in name:
|
||||
result = icons.get("desktop")
|
||||
|
||||
# Guess icon based on IP address ranges
|
||||
elif ip.startswith("192.168.1."):
|
||||
result = icons.get("laptop")
|
||||
|
||||
|
||||
return result
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Guess device type
|
||||
def guess_type(vendor, mac, ip, name, default):
|
||||
result = default
|
||||
mac = mac.upper()
|
||||
vendor = vendor.lower()
|
||||
name = name.lower()
|
||||
|
||||
# Guess icon based on vendor
|
||||
if any(brand in vendor for brand in {"samsung", "motorola"}):
|
||||
result = "Phone"
|
||||
elif "cisco" in vendor:
|
||||
result = "Router"
|
||||
elif "lg" in vendor:
|
||||
result = "TV"
|
||||
elif "google" in vendor:
|
||||
result = "Phone"
|
||||
elif "ubiquiti" in vendor:
|
||||
result = "Router"
|
||||
|
||||
# Guess type based on MAC address patterns
|
||||
elif mac == "INTERNET":
|
||||
result = "Internet"
|
||||
|
||||
# Guess type based on name
|
||||
elif 'google' in name:
|
||||
result = "Phone"
|
||||
|
||||
# Guess type based on IP address ranges
|
||||
elif ip == ("192.168.1.1"):
|
||||
result = "Router"
|
||||
|
||||
return result
|
||||
|
||||
@@ -145,7 +145,7 @@ def importConfigs (db, all_plugins):
|
||||
# UI
|
||||
conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian (it_it)', 'Portuguese (pt_br)', 'Polish (pl_pl)', 'Turkish (tr_tr)', 'Chinese (zh_cn)' ]", 'UI')
|
||||
conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "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": "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": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4'] , c_d, 'Icons', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "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": "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": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9J2ZhIGZhLXdpZmknPjwvaT4=', 'PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4', 'PGkgY2xhc3M9J2ZhIGZhLWdhbWVwYWQnPjwvaT4'] , c_d, 'Icons', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "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": "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": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_REFRESH = ccd('UI_REFRESH', 0 , c_d, 'Refresh interval', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'UI')
|
||||
conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['Tile Cards', 'Device Presence']", 'UI')
|
||||
conf.UI_PRESENCE = ccd('UI_PRESENCE', ['online', 'offline', 'archived'] , c_d, 'Include in presence', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['online', 'offline', 'archived']", 'UI')
|
||||
|
||||
Reference in New Issue
Block a user