mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-11 04:31:25 -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",
|
"function": "VERIFY_SSL",
|
||||||
"type": {
|
"type": {
|
||||||
|
|||||||
@@ -196,57 +196,69 @@ def get_pihole_network_devices():
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def gather_device_entries():
|
def gather_device_entries():
|
||||||
"""
|
"""
|
||||||
Build a list of device entries suitable for Plugin_Objects.add_object.
|
Build a list of device entries.
|
||||||
Each entry is a dict with: mac, ip, name, macVendor, lastQuery
|
Online status is determined by comparing lastSeen (in seconds) vs the current time.
|
||||||
"""
|
"""
|
||||||
entries = []
|
entries = []
|
||||||
|
|
||||||
iface_map = get_pihole_interface_data() # mac -> [ips]
|
|
||||||
devices = get_pihole_network_devices()
|
devices = get_pihole_network_devices()
|
||||||
now_ts = int(datetime.datetime.now().timestamp())
|
now_ts = int(datetime.datetime.now().timestamp())
|
||||||
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
hwaddr = device.get('hwaddr')
|
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
|
continue
|
||||||
|
|
||||||
macVendor = device.get('macVendor', '')
|
|
||||||
lastQuery = device.get('lastQuery')
|
|
||||||
|
|
||||||
# collect all IPs for this device
|
|
||||||
device_ips = device.get('ips', [])
|
device_ips = device.get('ips', [])
|
||||||
if not device_ips:
|
if not device_ips:
|
||||||
continue
|
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:
|
for ip_info in device_ips:
|
||||||
ip = ip_info.get('ip')
|
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
|
continue
|
||||||
|
|
||||||
name = ip_info.get('name') or '(unknown)'
|
name = ip_info.get('name') or '(unknown)'
|
||||||
|
tmp_mac = hwaddr.lower()
|
||||||
|
|
||||||
# Determine if this device is "online"
|
# Handle Fake MAC logic for non-standard hardware addresses
|
||||||
online = any(ip in iplist for iplist in iface_map.values())
|
if PIHOLEAPI_FAKE_MAC and not is_mac(tmp_mac):
|
||||||
|
tmp_mac = string_to_fake_mac(ip)
|
||||||
# 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 ''
|
|
||||||
|
|
||||||
entries.append({
|
entries.append({
|
||||||
'mac': tmpMac,
|
'mac': tmp_mac,
|
||||||
'ip': ip,
|
'ip': ip,
|
||||||
'name': name,
|
'name': name,
|
||||||
'macVendor': macVendor,
|
'macVendor': mac_vendor,
|
||||||
'lastQuery': last_query_val
|
# Pass the Unix timestamp as a string for NAX tracking
|
||||||
|
'lastQuery': str(max_last_seen) if max_last_seen > 0 else ""
|
||||||
})
|
})
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
@@ -255,7 +267,7 @@ def gather_device_entries():
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def main():
|
def main():
|
||||||
"""Main plugin entrypoint."""
|
"""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.'])
|
mylog('verbose', [f'[{pluginName}] start script.'])
|
||||||
|
|
||||||
@@ -272,6 +284,11 @@ def main():
|
|||||||
PIHOLEAPI_VERIFY_SSL = get_setting_value('PIHOLEAPI_SSL_VERIFY')
|
PIHOLEAPI_VERIFY_SSL = get_setting_value('PIHOLEAPI_SSL_VERIFY')
|
||||||
PIHOLEAPI_RUN_TIMEOUT = get_setting_value('PIHOLEAPI_RUN_TIMEOUT')
|
PIHOLEAPI_RUN_TIMEOUT = get_setting_value('PIHOLEAPI_RUN_TIMEOUT')
|
||||||
PIHOLEAPI_GET_OFFLINE = get_setting_value('PIHOLEAPI_GET_OFFLINE')
|
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
|
# Authenticate
|
||||||
if not pihole_api_auth():
|
if not pihole_api_auth():
|
||||||
|
|||||||
Reference in New Issue
Block a user