HVAC Network Scanner

Find out what's on a building automation network, without changing anything on it.

BACnet/IP and MS/TP, BACnet/SC, Modbus TCP, KNXnet/IP, Niagara Fox, Siemens APOGEE P2, SNMP and the web interfaces around them. It names each controller's model, reads its points, flags factory-default logins and writes a survey report you can hand to the building owner.

Free and open source (MIT). Windows 10 and 11 as an executable; anywhere Python 3.10 runs from source, with no other packages. All releases

HVAC Network Scanner after a scan: a device list of Trane, Siemens, Johnson Controls and other controllers with their models, vendors and points, and the scan log below

What it finds

BACnet, all of it

Every controller that answers a Who-Is, the MS/TP devices behind each router (also on other subnets, with no BBMD), BBMD tables, and each device's points with values, units and alarm state.

The exact model

Signals from every protocol combined: Trane Tracer SC+ and UC600, Siemens Desigo PXC and DXR2, Johnson Controls FEC and NAE, Niagara JACEs, Schneider, Carrier, Distech, KMC and more.

Not just BACnet

Modbus TCP devices and gateways with their registers, KNX IP interfaces, Niagara stations (version, host ID, brand), APOGEE P2 panels, OPC UA, S7, EtherNet/IP, MQTT, and every HVAC web interface's title and certificate.

Trends, schedules, alarms

What each trend log records and whether it has stopped, each schedule's week and what it controls, and who gets each alarm: a notification class routed to no one, or to a workstation long gone, stands out.

A report for the owner

Findings ranked by severity (factory-default logins on a reachable interface, cleartext logins, BACnet/SC or KNX gateways open to anyone, expired certificates, points in alarm), the inventory and open services, in one HTML file. Plus a point list as CSV.

What changed since last time

Compare a scan with an earlier one: devices that appeared or went quiet, new firmware, a model or address that changed. Run it nightly from the command line and alert only on change.

Screens

The BACnet Points tab: points with present values, units and status, alarms and overrides highlighted
Every point read, with value, units and status; alarms red, overrides amber.
The Trends, Schedules and Alarms tab: trend logs with their interval and state, schedules with their weekly programme, notification classes with their recipients
Trend logs, schedules and alarm routing, read as metadata.

Screens from the simulated site that comes with the scanner (tools/sim_site.py): made-up controllers on this PC's loopback addresses, so you can try it without a building.

Gentle by design

It reads; it doesn't write

  • BACnet: Who-Is, Who-Is-Router-To-Network, Read-BDT/FDT, ReadProperty and ReadPropertyMultiple. No writes, no reinitialize, no subscriptions.
  • Modbus: identification and register reads to a few unit IDs; never unit 0, never a write.
  • KNX: one description request, no connection.
  • APOGEE P2: one identify frame with a deliberately wrong network name; nothing registered.
  • Web and other services: connect, read the banner or GET /, close. Nothing logs in.

And keeps the load small

  • One request at a time to any controller, and one conversation at a time on an MS/TP trunk.
  • Batched reads sized to what each device can send back, so small MS/TP controllers don't abort.
  • At most two connection attempts to a host at once; a rate limit for fragile sites.
  • Never takes UDP 47808 from BACnet software already running on the PC.
  • Hostile or broken devices can't hang or crash a scan.

Two exceptions, said plainly

SNMP asks with a community string (public unless you set others), which is a password of sorts: an agent may log a wrong one. Turn SNMP off if that matters. BBMD registration, off unless you ask for it, adds the scanner to the BBMD's foreign-device table for at most five minutes after the scan, so its broadcasts reach other subnets. Factory-default logins are shown so the owner can check they were changed; they are never tried.

Only scan networks you own or are authorized to assess. Building systems can react badly to traffic they don't expect.

Install

Windows 10 and 11

Download HVACNetworkScanner.exe and run it: one file, nothing to install. It isn't code-signed, so SmartScreen says "Windows protected your PC" (More info → Run anyway). Check the file first; its SHA-256 is in the release notes:

Get-FileHash .\HVACNetworkScanner.exe -Algorithm SHA256

GitHub Actions builds it from the tagged commit and signs an attestation saying so; with the GitHub CLI:

gh attestation verify .\HVACNetworkScanner.exe --repo jamesccupps/HVAC-Network-Scanner

If Windows Firewall asks, allow it on the networks you scan: replies to a BACnet broadcast are dropped otherwise.

Any OS, with Python 3.10 or newer

The standard library is all it needs. Install it, then start the window or the command line:

pip install git+https://github.com/jamesccupps/HVAC-Network-Scanner.git
hvac-scanner-gui

A scan from the command line, with the survey report and the point list:

hvac-scanner 10.0.0.0/24 --html survey.html --points-csv points.csv

Try it without a building: git clone the repository, run python tools/sim_site.py, and scan 127.0.0.2-30.

Tested against

Supervisory controllersTrane Tracer SC+ (5,000+ objects), Trane Tracer Ensemble, Siemens Desigo CC / Insight
Field panelsSiemens PXC Compact and Modular (a 1,960-object program), Trane Symbio 400-500 on MS/TP
Room controllersSiemens DXR2
So farAbout 13,000 points read and 30,000 BACnet exchanges without a wire-level error. For hardware not listed, a size-based heuristic sets how much to read; a device profile from your scan helps the next person.

Feedback

Found a bug, or scanned gear it didn't recognise? Open an issue. The command-line reference, the changelog and the roadmap are in the README. Siemens APOGEE P2 sites: see the P2 scanner and Wireshark dissector.