# Netscan

The `netscan` plugin pings a list of devices on the local network and reports whether each one answers and how fast. It needs no credentials. Turn it on for the gear in an office or rack that can't run an agent: switches, printers, access points, the router, a NAS, phones.

For deeper numbers from the same devices, such as toner levels or port states, add the [SNMP](./snmp.md) or [TP-Link](./tplink.md) plugin. Reports for the same IP merge into one device on the dashboard.

## Enable it

Add `netscan` to the `plugins` array.

```json
{
  "plugins": ["netscan"],
  "netscan": {
    "refreshInterval": 30000,
    "pingCount": 2,
    "pingTimeout": 2,
    "devices": [
      { "name": "core-switch", "ip": "192.0.2.2", "type": "switch" },
      { "name": "office-printer", "ip": "192.0.2.20", "type": "printer" },
      { "name": "nas-01", "ip": "192.0.2.30", "type": "nas", "warnMs": 50 },
      { "name": "upstairs-ap", "ip": "192.0.2.40", "type": "ap", "mac": "00:00:5e:00:53:01" }
    ]
  }
}
```

| Option | Default | What it does |
| --- | --- | --- |
| `refreshInterval` | `30000` | Milliseconds between scans. |
| `pingCount` | `2` | Echo requests per device. |
| `pingTimeout` | `2` | Seconds to wait for each reply, passed to `ping -W`. |
| `devices` | `[]` | Devices to ping. Entries without `ip` are skipped. |
| `devices[].name` | the IP | Display name. |
| `devices[].ip` | required | Address to ping. |
| `devices[].type` | `host` | Free-form label such as `switch`, `printer`, `ap`, `nas`. Stored in the payload, not used for alerting. |
| `devices[].mac` | none | Stored with the device. |
| `devices[].warnMs` | `200` | Average round trip in milliseconds above which the device is slow. |

All devices are pinged at the same time on each pass.

## What it reports

One payload per device: `name`, `ip`, `type`, `mac`, `up`, `latency` (average round trip in ms, one decimal), `loss` (packet loss percent) and `warnMs`.

A device with 100% loss is reported down even if `ping` exited cleanly.

## When it alerts

| Severity | Trigger | Reason text |
| --- | --- | --- |
| error | `up` is false | `<name> (<ip>) unreachable` |
| warning | `latency` is above `warnMs` | `<name>: high latency <n>ms` |

Packet loss below 100% does not alert.

Netscan reports do not get their own service. The server folds them into a `device` entity keyed by IP, `dev-<ip>`, together with any SNMP or TP-Link report for the same address. Each plugin's payload sits under `data.sources.<plugin>`, and the device status is the worst status across its sources.

Device alerts go out on the first bad report, with no one-report wait, under source `device`. While an alert for that device is open, further bad reports don't send another. The server never resolves device alerts when the device recovers, so after the first one, the device does not page again until someone resolves the alert by hand. 
## On the dashboard

Netscan adds a PING metric to the front of the device card. It shows DOWN in red when the device is down, the latency in amber when it is above `warnMs`, and the latency in green otherwise.

A device with only a netscan source shows as "Device · &lt;ip>". When SNMP or TP-Link also reports for that IP, their metrics fill the rest of the card and their name for the device replaces the netscan name.

A device with no report from any source for 300 seconds shows OFFLINE.

## Requirements

- A `ping` binary on the agent host. It runs `ping -c <count> -W <timeout> <ip>`.
- The agent must reach the devices over ICMP. In a container, use host networking.

## Gotchas

- `-W` means seconds in Linux iputils ping. BSD and macOS ping read it differently. - Some devices drop ICMP but answer SNMP. For those, the SNMP plugin's reachability is the better signal.
