# What a BACnet discovery sweep actually tells you

> Who-Is stops at the subnet, I-Am carries no device name, and an object list from a device that cannot segment has to be read one index at a time.

Source: https://plantroomlabs.com/notes/bacnet-discovery-what-who-is-finds/  
Published: 2026-09-27 (27 September 2026) · Plantroom Labs  
Topics: BACnet, Discovery, Commissioning

Discovery feels like a question about the network. It is really four separate protocol facts, and three of them are about what you did not receive.

## What Who-Is and I-Am are

Two unconfirmed services, which is the protocol's way of saying nobody acknowledges anything. You broadcast a Who-Is; every device that hears it and falls inside the range you asked for answers with an I-Am. There is no transaction, no retry and no completion: a sweep is over when you stop listening, not when the network has finished telling you things.

Who-Is takes an optional low and high device instance, and with neither it means "everybody". Instance numbers are a 22-bit space — 0 to 4194302 — and the top value, 4194303, is reserved to mean *unknown*. A device answering with that has never been given an instance number, which is worth spotting: it is not on anyone's schedule and it will collide with the next unconfigured device on the same network.

Implementations commonly stagger their replies to keep a global Who-Is from turning into a broadcast storm, so replies keep arriving well after the round trip you would expect. A sweep that listens for one second and a sweep that listens for ten can legitimately return different device counts.

## What an I-Am does not contain

Four fields: the device identifier, the largest message the device will accept, whether it supports segmentation, and the vendor identifier. That is all.

**There is no device name in an I-Am.** Every tool that shows you a named device list has quietly done a second step — reading the Device object's object-name property from each responder — and that step is a confirmed request that can fail on its own. A device that appears in a sweep with no name has not necessarily got a blank name; it may simply not have answered the follow-up.

The two middle fields are more useful than they look, because they are a prediction. The maximum APDU length tells you how much can come back in one message: around 1476 bytes is typical for a device on Ethernet, and 480 is typical for one behind an MS/TP trunk, which is a strong hint that the device you are about to interrogate is not actually on the IP network at all. Segmentation support tells you whether a long reply can be split across messages, and that single flag decides how the next section goes.

## Reading an object list from a device that cannot segment

The obvious move is to read the Device object's object-list property and get an array of every object on the device. On a device with segmentation and a few dozen objects, that works and it is one request.

On a device with no segmentation support, a long object-list does not come back truncated. The request is abandoned — an Abort, because the reply will not fit in one message — and a tool that treats that as "the device has no objects" is wrong in the most confusing possible way.

The way through is a property of BACnet arrays that is easy to work for years without meeting: **reading an array property at index 0 returns the number of elements**, not the first element. So you read object-list at index 0, get a count, and then read indices 1 to *n* one at a time. It is n+1 requests instead of one, it is slow on an MS/TP trunk, and it always works.

> **Why this matters beyond tooling.** The same asymmetry is behind "discovery found the device but no points" in every BMS head end, including Niagara. The device is fine. The reply was too big for one message and nothing was configured to fall back.

## Why the sweep stops at the subnet, and what a BBMD really does

BACnet/IP broadcasts are IP broadcasts, and IP broadcasts do not cross a router. The fix in the standard is a BBMD: one device per subnet that keeps a table of its peers and re-broadcasts what arrives.

Two details decide whether this works on a real estate. The first is that each entry in a BBMD's table carries a distribution mask, and the mask chooses between two very different behaviours. With a mask that names the peer alone, the BBMD sends a forwarded copy to that peer, which then broadcasts it locally — two hops, and it works through any router. With an all-ones mask, the BBMD sends a directed broadcast straight into the remote subnet — one hop, and most enterprise routers drop directed broadcasts, so it silently does nothing. A BBMD table that was built one way and a network that was later re-configured the other way is one of the commonest causes of "we can see half the site".

The second is that a laptop cannot be a BBMD's peer; it registers as a foreign device instead, and that registration carries a time to live. It has to be renewed while you are working, or broadcasts stop reaching you part way through a long job — which looks exactly like devices dropping off the network, and is not.

The practical consequence for any sweep from a laptop, ours included: what you are looking at is one broadcast domain. On a site with MS/TP trunks behind routers, see [BACnet MS/TP on a JACE](https://plantroomlabs.com/notes/bacnet-mstp-on-a-jace/) for what those trunks cost you in speed and message size once you do reach them.

## What a present value does not tell you

A dump of present values looks like the truth. Three properties alongside it decide whether it is.

**out-of-service.** When it is true, the object's present value is deliberately disconnected from the physical input and becomes writable — that is what the property is for. Somebody forced a value to commission a control loop, or to silence an alarm at two in the morning, and true is the state they left it in. The number reads perfectly. It is not a measurement. This is the single most useful column in a point dump and the one most often left out of one.

**status-flags and reliability.** Status-flags carries the in-alarm, fault, overridden and out-of-service bits in one place, and reliability says what kind of fault — open circuit, shorted, over range, no sensor. A point can be reporting a plausible number with fault set and nothing upstream looking at it.

**units, when it comes back as a number.** The engineering units enumeration reserves values up to 255 for the standard; anything from 256 up is the vendor's own. So a units value that prints as a bare number rather than a name is not a bug in your tool — it is a proprietary unit, and only the vendor's documentation can say what it means. Assume nothing about scaling until it is confirmed.

## Two findings worth acting on immediately

**Two devices with the same instance number.** Perfectly possible to configure, and nothing on the wire stops it. In a sweep it shows up as two I-Am replies carrying the same instance from two different addresses, and any head end that keys devices by instance number keeps one and loses the other — usually whichever answered last, which can change between restarts. If a device "keeps disappearing", count the replies before you blame the network.

**Object names that are only unique locally.** The standard requires an object's name to be unique *within its device*; only the Device object's name has to be unique across the internetwork. So `Room Temp` on forty controllers is legal, and a point list keyed on name rather than on device-plus-object identifier will merge things that are not the same point. This is why naming and tagging conventions are applied as points are created, not afterwards: [bulk point renaming and tagging](https://plantroomlabs.com/notes/bulk-point-renaming-and-tagging/) is the cleanup when they were not.

We publish a small read-only sweep that does the discovery and the object list dump described here, including the index-at-a-time fallback: [bacnet-sweep](https://plantroomlabs.com/tools/bacnet-sweep/). It is free, it writes nothing, and the limits above are its limits too.
