With PIHOLEAPI_GET_OFFLINE enabled, PIHOLEAPI imports devices it considers
offline, but every row still counted as a live sighting. The plugin
computed the online state, yet never passed it on, and its config.json
mapped nothing to CurrentScan.scanPresence, so each row got the column
default 1. An offline device imported only for its name, vendor and IP
was marked online. ADGUARDIMP had the same problem in #1813 and fixed it
the same way.
Changes:
- main() passes the online state as helpVal4 '1' or '0' to add_object()
(server/plugins/pihole_api_scan/pihole_api_scan.py).
- config.json maps helpVal4 to scanPresence, the same column definition
adguard_import uses. The GET_OFFLINE description says offline devices
are imported without being marked online; the README says the same.
- test/db_test_helpers.py: make_plugin_event_row() takes an optional
help_val4, and CREATE_CURRENT_SCAN gets the
CHECK (scanPresence IN (0, 1)) of the real schema (db_upgrade.py), so a
test sees the same constraint as production.
- New test/scan/test_piholeapi_scan_presence_mapping.py runs the real
PIHOLEAPI config.json through process_plugin_events() and checks that a
helpVal4 '0' row lands in CurrentScan with scanPresence 0.
- test/plugins/test_pihole_api_scan.py: main() writes helpVal4 '0' for an
offline device and '1' for every IP row of an online device. Both new
tests fail without this change.
Impact:
Devices imported only because of PIHOLEAPI_GET_OFFLINE keep their name,
vendor and IP data but no longer mark the device as online. Live check
against Pi-hole v6.8: 28 rows with helpVal4 '0', 5 with '1'; the absent
phone got devPresentLastScan 0 and only a New Device event. With
GET_OFFLINE disabled (the default) every imported row is online, so
nothing changes there.
Devices reported by PIHOLEAPI stayed online for about 24 hours after they
left the network (follow-up to #1436). The online check compared
PIHOLEAPI_CONSIDER_ONLINE with the freshest ips[].lastSeen of a device.
Pi-hole FTL v6.8 sets lastSeen to "now" on every network table update for
every client it still holds in memory, also when the client is not in the
ARP cache (src/database/network-table.c, add_FTL_clients_to_network_table()
calls add_netDB_network_address()). In a live run against Pi-hole v6.8 all
22 devices the old code reported as online had a lastSeen of 36 s, among
them a phone whose last DNS query was 18 h old.
Changes:
- New is_device_online(last_query, now_ts, consider_online) in
server/plugins/pihole_api_scan/pihole_api_scan.py. A device is online if
its last DNS query is at most consider_online seconds old; a lastQuery
of 0 (never queried) is always offline.
- gather_device_entries() reads the device lastQuery instead of looping
over ips[].lastSeen, and each entry carries 'isOnline'. The 'lastQuery'
field (shown as "Last Query") now holds the real lastQuery.
- PIHOLEAPI_CONSIDER_ONLINE gets a module-level default of 300, like the
other setting globals.
- The verbose line for a skipped offline device names the MAC and the
age of its last DNS query instead of dumping the whole device dict.
- config.json: CONSIDER_ONLINE is labeled "Online if last query" and its
description says the window applies to the last DNS query.
- README: lists "Time of the last DNS query" and explains that online
status comes from DNS activity, that quiet devices can show as offline,
and what to do (presence scanner on the same schedule, or a larger
CONSIDER_ONLINE when PIHOLEAPI is the only presence source).
- New test/plugins/test_pihole_api_scan.py (module stubs as in
test_adguard_import.py): the reported case, the CONSIDER_ONLINE
boundary, clock skew, a missing or zero lastQuery, a device with two
IPs. All 10 tests fail on the old code.
Impact:
A device goes offline in PIHOLEAPI CONSIDER_ONLINE seconds after its last
DNS query, not about 24 hours later. Behavior change: a device that is on
but sends no DNS query within that window is not reported as online by
PIHOLEAPI any more. Setting keys and defaults are unchanged.