mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-03-30 23:03:03 -07:00
PLG: add PIHOLEAPI_CONSIDER_ONLINE #1436
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -263,6 +263,34 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CONSIDER_ONLINE",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 300,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Online if last seen"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Time in seconds to consider a device online."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "VERIFY_SSL",
|
||||
"type": {
|
||||
|
||||
@@ -196,57 +196,69 @@ def get_pihole_network_devices():
|
||||
# ------------------------------------------------------------------
|
||||
def gather_device_entries():
|
||||
"""
|
||||
Build a list of device entries suitable for Plugin_Objects.add_object.
|
||||
Each entry is a dict with: mac, ip, name, macVendor, lastQuery
|
||||
Build a list of device entries.
|
||||
Online status is determined by comparing lastSeen (in seconds) vs the current time.
|
||||
"""
|
||||
entries = []
|
||||
|
||||
iface_map = get_pihole_interface_data() # mac -> [ips]
|
||||
devices = get_pihole_network_devices()
|
||||
now_ts = int(datetime.datetime.now().timestamp())
|
||||
|
||||
for device in devices:
|
||||
hwaddr = device.get('hwaddr')
|
||||
if not hwaddr or hwaddr == "00:00:00:00:00:00":
|
||||
|
||||
# Filter out invalid MACs/interfaces
|
||||
if not hwaddr or hwaddr in ["00:00:00:00:00:00", "ip-::"]:
|
||||
continue
|
||||
|
||||
macVendor = device.get('macVendor', '')
|
||||
lastQuery = device.get('lastQuery')
|
||||
|
||||
# collect all IPs for this device
|
||||
device_ips = device.get('ips', [])
|
||||
if not device_ips:
|
||||
continue
|
||||
|
||||
# 1. Find the freshest timestamp across all IPs for this MAC
|
||||
# This ensures if the device is active on ANY IP, the MAC is considered online.
|
||||
max_last_seen = 0
|
||||
for ip_info in device_ips:
|
||||
ls = ip_info.get('lastSeen', 0)
|
||||
if ls > max_last_seen:
|
||||
max_last_seen = ls
|
||||
|
||||
# 2. Determine online status: (Current Time - Last Seen) <= PIHOLEAPI_CONSIDER_ONLINE
|
||||
# Math is in seconds.
|
||||
if (now_ts - max_last_seen) <= PIHOLEAPI_CONSIDER_ONLINE:
|
||||
is_online = True
|
||||
else:
|
||||
is_online = False
|
||||
|
||||
# 3. Skip if offline (and user doesn't want offline devices)
|
||||
if not is_online and not PIHOLEAPI_GET_OFFLINE:
|
||||
mylog('verbose', [f'[{pluginName}] Not online in the last {PIHOLEAPI_CONSIDER_ONLINE}s, import of offline disabled (PIHOLEAPI_GET_OFFLINE) skipping device: {device}.'])
|
||||
continue
|
||||
|
||||
mac_vendor = device.get('macVendor', '')
|
||||
|
||||
# 4. Process each valid IP for the device
|
||||
for ip_info in device_ips:
|
||||
ip = ip_info.get('ip')
|
||||
if not ip:
|
||||
|
||||
# Skip internal Pi-hole placeholders
|
||||
if not ip or ip in ["0.0.0.0", "::"]:
|
||||
mylog('verbose', [f'[{pluginName}] Not a valid ip ({ip}), skipping device: {device}.'])
|
||||
continue
|
||||
|
||||
name = ip_info.get('name') or '(unknown)'
|
||||
tmp_mac = hwaddr.lower()
|
||||
|
||||
# Determine if this device is "online"
|
||||
online = any(ip in iplist for iplist in iface_map.values())
|
||||
|
||||
# Skip offline devices unless PIHOLEAPI_GET_OFFLINE=True
|
||||
if not online and not PIHOLEAPI_GET_OFFLINE:
|
||||
continue
|
||||
|
||||
tmpMac = hwaddr.lower()
|
||||
|
||||
# ensure fake mac if enabled
|
||||
if PIHOLEAPI_FAKE_MAC and not is_mac(tmpMac):
|
||||
tmpMac = string_to_fake_mac(ip)
|
||||
|
||||
# mark lastQuery as now if online, else keep original
|
||||
last_query_val = str(now_ts) if online else str(lastQuery) if lastQuery else ''
|
||||
# Handle Fake MAC logic for non-standard hardware addresses
|
||||
if PIHOLEAPI_FAKE_MAC and not is_mac(tmp_mac):
|
||||
tmp_mac = string_to_fake_mac(ip)
|
||||
|
||||
entries.append({
|
||||
'mac': tmpMac,
|
||||
'mac': tmp_mac,
|
||||
'ip': ip,
|
||||
'name': name,
|
||||
'macVendor': macVendor,
|
||||
'lastQuery': last_query_val
|
||||
'macVendor': mac_vendor,
|
||||
# Pass the Unix timestamp as a string for NAX tracking
|
||||
'lastQuery': str(max_last_seen) if max_last_seen > 0 else ""
|
||||
})
|
||||
|
||||
return entries
|
||||
@@ -255,7 +267,7 @@ def gather_device_entries():
|
||||
# ------------------------------------------------------------------
|
||||
def main():
|
||||
"""Main plugin entrypoint."""
|
||||
global PIHOLEAPI_URL, PIHOLEAPI_PASSWORD, PIHOLEAPI_API_MAXCLIENTS, PIHOLEAPI_VERIFY_SSL, PIHOLEAPI_RUN_TIMEOUT, PIHOLEAPI_GET_OFFLINE
|
||||
global PIHOLEAPI_URL, PIHOLEAPI_PASSWORD, PIHOLEAPI_API_MAXCLIENTS, PIHOLEAPI_VERIFY_SSL, PIHOLEAPI_RUN_TIMEOUT, PIHOLEAPI_GET_OFFLINE, PIHOLEAPI_CONSIDER_ONLINE
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] start script.'])
|
||||
|
||||
@@ -272,6 +284,11 @@ def main():
|
||||
PIHOLEAPI_VERIFY_SSL = get_setting_value('PIHOLEAPI_SSL_VERIFY')
|
||||
PIHOLEAPI_RUN_TIMEOUT = get_setting_value('PIHOLEAPI_RUN_TIMEOUT')
|
||||
PIHOLEAPI_GET_OFFLINE = get_setting_value('PIHOLEAPI_GET_OFFLINE')
|
||||
PIHOLEAPI_CONSIDER_ONLINE = get_setting_value('PIHOLEAPI_CONSIDER_ONLINE')
|
||||
|
||||
# Fallback in case the setting is missing or returned as an empty string
|
||||
if not isinstance(PIHOLEAPI_CONSIDER_ONLINE, int):
|
||||
PIHOLEAPI_CONSIDER_ONLINE = 300
|
||||
|
||||
# Authenticate
|
||||
if not pihole_api_auth():
|
||||
|
||||
Reference in New Issue
Block a user