Skip to content

Tools

Free tools for reading a building's network, its paperwork, and a release before it ships

Fourteen small programs, given away because they cost nothing to give. Three of them read a network: one sweeps it for BACnet devices and dumps a device's points, one watches an MQTT broker and prints its topic tree, one runs a LoRaWAN vendor's payload decoder and reports what a station would get back from it. Nine read what Niagara itself will do with a setting, a point file, a signed module, a gateway's object type, an alarm's route, a recipient whose far end is down or a schedule's next change, before any of it reaches a station. One more is for the spreadsheet a business runs on: it opens an .xlsx as the zip of XML it is and reports what the sheet encodes. And one is for a website on its way to production: it reads the same list of paths on two hosts and reports every field that moved, so a release cannot change what a client's rankings rest on without somebody having written it down. All fourteen are read-only, all fourteen are one file, and none of them needs anything installed beyond the runtime already on the machine.

  • Read-only
  • Python 3 · Node 18
  • No dependencies
  • One file
  • MIT licensed
  • No account

Nothing is gated. No account, no sign-up, no email address, and no download form — the file downloads with a click, and each one is a public MIT-licensed repository you can clone instead.

Why these exist

The first hour on an unfamiliar site is always the same hour. What is on this network. What is it called. Is that value real. The tools that answer those questions well are either a vendor's, or licensed to a laptop that is not yours, or excellent and free and installed on a machine you are not allowed to install anything on.

So these are deliberately small. One file each, no package to install, nothing to register, and no ability to change anything in the building. Copy the file onto whatever laptop you have, run it, read the output, delete it. Thirteen of them are Python 3 and standard library only; decoder-check is Node 18 or newer and uses nothing outside the Node standard library either.

Another nine answer a different first hour. Not what is on the network, but what this framework will quietly do with what you are about to give it — the register a Modbus point really asks for, the columns an EDE import replaces with a default and does not mention, which verification mode refuses the module you signed, whether a write goes through a priority array or straight to present-value, which duplicate alarm the queue discards and reports as delivered, what a recipient does when the far end is down, and how far ahead a schedule can see. Each reads the framework's own code out of a Niagara installation rather than repeating a manual, so the answer is the one your version will actually give.

And one answers a question nobody asks about a control system, because the thing it reads is not one. The spreadsheet a department runs on is undocumented software with no version control, no tests, and nobody left who knows why a cell holds the number it holds. workbook-scan opens it as the zip of XML it is and reports what the file encodes, which is the only honest first step before anybody offers to replace it.

And one is not about a building at all. Asked what gets an outsourced developer dropped, an agency owner who buys development that way answered that it is not bad code, it is silent changes — a URL pattern that moved, a dropped canonical, an h1 turned into a styled div, a noindex that never came off, an analytics tag quietly not firing. The site works perfectly afterwards and the rankings slide three weeks later. release-diff is the instrument that same person named: read the same paths on both sides of a release, report everything that moved, and fail on anything that moved and was not declared. A launch checklist cannot do it, because a checklist only catches what somebody already thought to write down.

Thirteen of the fourteen are a file you download and run. ede-check is also hosted here: the same checks, running in your browser, on an EDE file that is never uploaded. It is the only page on this site that executes something for you, and the reason it can be offered at all is that there is nowhere for the file to go.

They are not replacements for the tools you already use. They are narrower than all of them on purpose: a sweep and a dump, a tap and a tree. Where a general-purpose explorer is better, use the explorer — each page says so.

How they are licensed, and where the source is

Every file here is MIT (LICENSE.txt), and each tool's repository carries the same licence as its own LICENSE file. In practice that means you can read it, change it, keep the changed copy, put it on a site laptop that is not yours, or ship it inside something you sell. The one condition is that the copyright line and the permission notice travel with the copy, and since 2026-10-04 they do on their own: the licence block is inside each script, as an SPDX-License-Identifier line and the copyright, so a single file downloaded on its own still says what it is. The fuller text is in LICENSE.txt and in every repository. This page claimed that for weeks before it was true - no served script carried a notice until the day it was found - so check.py now holds the sentence to the served bytes in both directions.

Each one also has a public repository, holding the same file plus everything needed to re-run the checks its page relies on — the fixtures and suites the claims rest on, rather than a description of them: bacnet-sweep · mqtt-tap · decoder-check · modbus-address-scan · ede-check · module-sign-scan · bacnet-priority-scan · alarm-route-scan · alarm-recipient-scan · schedule-scan · workbook-scan · poll-scheduler-scan · tuning-stale-scan · release-diff. The download here and the file in the repository are the same bytes; each page publishes the size and SHA-256, so that is checkable rather than asserted. Issues and pull requests are read.

There is also nothing to activate. No key, no account, no registration, no phone-home — the scripts make exactly the network connections their pages describe and no others.

All free

Three that read the network

Also free

Nine that read what Niagara will do with your file

No network, no station and no import: they read the shipped jars and report what the framework is built to do with the settings, the file and the module you already have.

Also free

One for the spreadsheet a business runs on

Not a control system at all. A workbook a department depends on is undocumented software too, and the first honest step is reading what it already does.

Also free

One for a release on its way to production

Not a control system either. A website release can change what a client's search rankings rest on without anybody being able to see it on the page, and the only instrument that finds that is a comparison of the two renderings.

What "read-only" means here

It means something mechanical in both cases, not a promise about intent. bacnet-sweep can encode two BACnet services and no others, Who-Is and ReadProperty, and a gate function raises before any packet leaves if anything else is ever passed to the request builder. mqtt-tap has no PUBLISH encoder in it at all; every outbound byte goes through one function that refuses any packet type outside CONNECT, SUBSCRIBE, PUBACK, PINGREQ and DISCONNECT, and mqtt-tap.py --self-check makes that refusal happen in front of you. Both files are one file, so anyone who wants to check rather than believe it can. decoder-check touches no network at all: it runs a decoder inside a node:vm context with no require, no process, no filesystem, no timers and no sockets, and its own self-check proves that a decoder trying to reach any of them fails rather than succeeds. The nine scanners open jars and a CSV for reading, and workbook-scan opens a zip and an OLE compound file the same way: none of them makes a network connection at all, and there is nothing in any of those files that can reach a station, which is why none of them needs one.

Read-only is not the same as no effect. A Who-Is makes every device on a subnet answer at once, and reading a large controller's object list is hundreds of requests to a device that also has a building to run. A new MQTT client that takes an identifier already in use gets the existing client disconnected, which is a way to cause an incident without publishing a byte. Both tools are built to avoid the second and to pace the first, and both pages say where it still matters.

What each one has actually been run against

This is the honest headline and it belongs above the fold rather than in a footnote. bacnet-sweep has never spoken to a real BACnet device; mqtt-tap has never connected to a real broker product. Each was proved against a fixture written from the protocol specification and run on loopback — 198 assertions for one, 130 for the other — and every terminal transcript on these pages is real output from that fixture, not from a site. A real controller or a real broker will differ. Each page has a section saying exactly what was and was not covered, and it is worth reading before you rely on either of them for anything that matters.

The nine scanners are measured rather than fixtured, and the measurement is of one machine: a Niagara 4.15.5.22 installation, read with the javap that ships with it. Every transcript on their pages is that run. The controller this work usually targets runs 4.14.0.162, and none of the nine has been run on a JACE. A different Niagara version is a different answer, which is why each one prints the installation it read and each page says to run it against yours.

decoder-check is the exception, and in the useful direction: it has been run against real published decoders — the JavaScript that device vendors ship for The Things Network and ChirpStack — and it found real defects in them. Those went to the maintainers privately, with a patch, which is why no vendor is named here or on its page. What it has never done is talk to a network server: it reads frames you give it, and nothing else.

Also free, and written for an agent rather than a person

obix-mcp (repository) is an MCP server that lets an AI agent read a Niagara station over oBIX — the lobby, points, folders, histories, and live values through server-side watches. It is read-only by default: the write tool is not merely refused when writes are off, it is absent from the tool list, and turning it on takes two separate decisions, one for the deployment and one for the subtree it may write to.

What makes it worth a look even if you never run it is EVIDENCE.md: every protocol decision cited to the class and method it was read out of in a Niagara 4.15 install, with the gaps stated as gaps rather than filled in from the specification. Three of those citations change what a client has to do — the export branch is mounted as continuousControl and not export; HTTP Basic is not enabled on a station by default, so a 401 is usually a missing scheme rather than a wrong password; and a 403 means either an unlicensed server or a refused object, with only the response body to tell them apart. Same caveat as the tools above: it has been proved against a fixture written from that evidence, and has never been pointed at a controller.

If you want the findings without the code, they are written up as notes: what a Niagara oBIX server actually exposes covers the surface, and letting an agent write to a control system covers the part that needs gates.

Also free, and not a program

The Niagara 5 module scan is the same idea pointed at a different problem: send a listing of a station's modules folder and a per-module readiness table comes back. That one we run rather than give away, because it needs a Java 25 JDK and a rule set rather than a laptop.

Next step

Found something you now have to fix?

Send the CSV, the topic list or the decoder report, and what the site is. You will get a written scope and a fixed price against it — or, if the honest answer is that this is a setting rather than a project, that instead.