From 771dd4b176eea22f65d6ceec2ee01d07017e1cbc Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Tue, 5 Aug 2025 14:02:48 +1000 Subject: [PATCH] docs --- docs/DEVICE_HEURISTICS.md | 47 +++---- docs/samples/API/Grafana_Dashboard.json | 172 +++++++++--------------- 2 files changed, 79 insertions(+), 140 deletions(-) diff --git a/docs/DEVICE_HEURISTICS.md b/docs/DEVICE_HEURISTICS.md index 9e609f31..082e56c0 100755 --- a/docs/DEVICE_HEURISTICS.md +++ b/docs/DEVICE_HEURISTICS.md @@ -1,9 +1,12 @@ -# Icon and Type guessing: Device heuristics +# Device Heuristics: Icon and Type Guessing This module is responsible for inferring the most likely **device type** and **icon** based on minimal identifying data like MAC address, vendor, IP, or device name. It does this using a set of heuristics defined in an external JSON rules file, which it evaluates **in priority order**. +>[!NOTE] +> You can find the full source code of the heuristics module in the `device_heuristics.py` file. + --- ## JSON Rule Format @@ -23,6 +26,9 @@ Rules are defined in a file called `device_heuristics_rules.json` (located under ] ``` +>[!NOTE] +> Feel free to raise a PR in case you'd like to add any rules into the `device_heuristics_rules.json` file. Please place new rules into the correct position and consider the priority of already available rules. + ### Supported fields: | Field | Type | Description | @@ -41,45 +47,30 @@ Rules are defined in a file called `device_heuristics_rules.json` (located under The function `guess_device_attributes(...)` runs a series of matching functions in strict order: -```text -1. MAC + Vendor → match_mac_and_vendor() -2. Vendor only → match_vendor() -3. Name pattern → match_name() -4. IP pattern → match_ip() -5. Final fallback → defaults -``` +1. MAC + Vendor → `match_mac_and_vendor()` +2. Vendor only → `match_vendor()` +3. Name pattern → `match_name()` +4. IP pattern → `match_ip()` +5. Final fallback → defaults defined in the `NEWDEV_devIcon` and `NEWDEV_devType` settings. -### Even if defaults are passed in, matching continues +### Use of default values -For example, when `default_icon` is passed in from an external source (like `NEWDEV_devIcon`), that value **does not halt the guessing process**. The matchers still try to find a better match: +The guessing process runs for every device **as long as the current type or icon still matches the default values**. Even if earlier heuristics return a match, the system continues evaluating additional clues — like name or IP — to try and replace placeholders. ```python -# Even if default_icon is passed, match_ip() and others will still run +# Still considered a match attempt if current values are defaults if (not type_ or type_ == default_type) or (not icon or icon == default_icon): type_, icon = match_ip(ip, default_type, default_icon) ``` -This is by design — you can pass in known fallbacks (e.g. `"unknown_icon"`), but the system will still guess and overwrite them **if it finds a better match**. - ---- - -## Defaults & Normalization - -Input sanitization ensures missing data doesn’t break detection: - -| Input | Normalized to | -| ------------- | --------------------- | -| `vendor=None` | `"unknown"` | -| `mac=None` | `"00:00:00:00:00:00"` | -| `ip=None` | `"169.254.0.0"` | -| `name=None` | `"(unknown)"` | - -These placeholder values **still go through the matching pipeline**. This makes the logic robust and ensures IP- or name-based matching can still work even if MAC/Vendor are unknown. +In other words: if the type or icon is still `"unknown"` (or matches the default), the system assumes the match isn’t final — and keeps looking. It stops only when both values are non-default (defaults are defined in the `NEWDEV_devIcon` and `NEWDEV_devType` settings). --- ## Match Behavior (per function) +These functions are executed in the following order: + ### `match_mac_and_vendor(mac_clean, vendor, ...)` * Looks for MAC prefix **and** vendor substring match @@ -109,7 +100,7 @@ These placeholder values **still go through the matching pipeline**. This makes * If missing, it falls back to the passed-in `default_icon` (`NEWDEV_devIcon` setting) * If a match is found but icon is still blank, default is used -**TL;DR:** If a match sets the type but has no icon, the default icon is used. If the match has both, defaults are overridden. +**TL;DR:** Type and icon must both be matched. If only one is matched, the other falls back to the default. --- diff --git a/docs/samples/API/Grafana_Dashboard.json b/docs/samples/API/Grafana_Dashboard.json index 211084b2..5c35d9a0 100755 --- a/docs/samples/API/Grafana_Dashboard.json +++ b/docs/samples/API/Grafana_Dashboard.json @@ -1,47 +1,4 @@ { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "panel", - "id": "barchart", - "name": "Bar chart", - "version": "" - }, - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "12.0.0" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "stat", - "name": "Stat", - "version": "" - }, - { - "type": "panel", - "id": "table", - "name": "Table", - "version": "" - } - ], "annotations": { "list": [ { @@ -61,14 +18,11 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": null, + "id": 7, "links": [], "panels": [ { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, + "datasource": "Prometheus", "fieldConfig": { "defaults": { "color": { @@ -77,8 +31,6 @@ }, "decimals": 0, "mappings": [], - "max": 105, - "min": 0, "thresholds": { "mode": "absolute", "steps": [ @@ -122,12 +74,8 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_total_devices", - "refId": "A", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "expr": "netalertx_connected_devices + netalertx_offline_devices", + "refId": "A" } ], "title": "Total Devices", @@ -136,7 +84,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -190,12 +138,12 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_connected_devices", - "refId": "A", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_connected_devices", + "refId": "A" } ], "title": "Connected", @@ -204,7 +152,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -259,12 +207,12 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_favorite_devices", - "refId": "A", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_favorite_devices", + "refId": "A" } ], "title": "Favorites", @@ -273,7 +221,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -328,12 +276,12 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_new_devices", - "refId": "A", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_new_devices", + "refId": "A" } ], "title": "New Devices", @@ -342,7 +290,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -397,12 +345,12 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_down_devices", - "refId": "A", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_down_devices", + "refId": "A" } ], "title": "Down", @@ -411,7 +359,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -466,12 +414,12 @@ "pluginVersion": "12.0.0", "targets": [ { - "expr": "netalertx_archived_devices", - "refId": "A", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_archived_devices", + "refId": "A" } ], "title": "Archived", @@ -480,7 +428,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "fieldConfig": { "defaults": { @@ -605,31 +553,31 @@ "pluginVersion": "12.0.0", "targets": [ { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, "expr": "netalertx_connected_devices", "legendFormat": "Connected", - "refId": "A", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "refId": "A" }, { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, "expr": "netalertx_total_devices - (netalertx_connected_devices + netalertx_down_devices)", "legendFormat": "Offline", - "refId": "B", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "refId": "B" }, { - "expr": "netalertx_down_devices", - "legendFormat": "Down Devices", - "refId": "C", "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "uid": "PBFA97CFB590B2093" + }, + "expr": "netalertx_down_devices", + "legendFormat": "Down Devices", + "refId": "C" } ], "title": "Device Presence", @@ -638,7 +586,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "description": "Connected (Online) Devices", "fieldConfig": { @@ -826,15 +774,15 @@ "pluginVersion": "12.0.0", "targets": [ { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, "editorMode": "code", "expr": "netalertx_device_status{device_status=\"Online\"}", "format": "table", "range": true, - "refId": "A", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "refId": "A" } ], "title": "Connected Devices", @@ -892,7 +840,7 @@ { "datasource": { "type": "prometheus", - "uid": "${DS_PROMETHEUS}" + "uid": "PBFA97CFB590B2093" }, "description": "Disconnected(Offline) Devices", "fieldConfig": { @@ -1079,15 +1027,15 @@ "pluginVersion": "12.0.0", "targets": [ { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, "editorMode": "code", "expr": "netalertx_device_status{device_status=\"Offline\"}", "format": "table", "range": true, - "refId": "A", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - } + "refId": "A" } ], "title": "Disconnected Devices", @@ -1143,6 +1091,7 @@ "type": "table" } ], + "preload": false, "refresh": "30s", "schemaVersion": 41, "tags": [], @@ -1156,7 +1105,6 @@ "timepicker": {}, "timezone": "browser", "title": "NetAlertX Overview", - "uid": "netalertx-overview_7_26_2025", - "version": 7, - "weekStart": "" + "uid": "netalertx-overview_8_4_2025", + "version": 2 } \ No newline at end of file