sondwave
BACNET/IP · DISCOVERY + RPM READ

Discover the BAS you have

broadcast scan+targeted scandevice statepoint model

01 DISCOVERY

Device
state

responding · enumerating · timed-out · rejected

AHU-140/40responding · 12 ms
VAV-204enumerating12/40
MTR-Main18/18responding · 31 ms
CTRL-7via MS/TPquerying · 3.2 s
RTU-3large RPMsegmentation-reject
FCU-119no I-Amtimed-out · 5 s
02 TOPOLOGY

Network
context

devices · networks · addresses · latency · point counts

◉ site:HQ — 3 nets · 214 points ├─ net:1 BACnet/IP backbone // -- ms │ ├─ ▸ AHU-1 ahu · 0.94 │ │ ├─ discharge-air-temp -- │ │ ├─ supply-fan-cmd -- │ │ └─ mixed-air-damper -- │ ├─ ▸ CH-1 chiller · 0.91 │ └─ ▸ MTR-Main elecMeter · 0.88 ├─ net:12 MS/TP trunk // 9600 baud · -- ms │ ├─ ▸ VAV-201..214 vav · ×14 │ └─ ▸ FCU-1..8 fcu · ×8 └─ net:20 Modbus TCP // -- ms └─ ▸ PWR-Panel meter · pm5560
AHU VAV Chiller FCU Meter Net / trunk Live value
03 TAGS

Tag
proposals

Haystack 4 vocabulary · source + confidence · corrections persist

1Protocol metadatanames · units · object type
2Rules & dictionariesdeterministic · on-box
3Equipment inferencedeterministic grouping
4Operator reviewcorrections persist
point · zinc
@p:1a4f dis:"Discharge Air Temp"
  point sensor temp air discharge
  equipRef:@e:AHU-1  siteRef:@s:HQ
  unit:"°F"  kind:"Number"
  curVal:54.6  curStatus:"ok"
  bacnetCur:"AI:3.presentValue"
source rules 0.00 ▸ correct inline → flywheel
04 EXPORT

Export
the model

devices · points · tags · units · current values

HQ-survey.csv · 214 points
id,dis,equip,net,unit,curVal,tags
@p:1a4f,Discharge Air Temp,AHU-1,1,°F,54.6,point sensor temp air discharge
@p:2b7c,Supply Fan Cmd,AHU-1,1,,on,point cmd fan
@p:3d19,Mixed Air Damper,AHU-1,1,%,38,point cmd damper
@p:5f22,Zone Temp,VAV-204,12,°F,71.2,point sensor temp air zone
@p:7a04,kW Demand,MTR-Main,1,kW,48.6,point sensor power elec
… 209 more rows
ver:"3.0"
id,dis,equipRef,unit,curVal,sensor,temp
@p:1a4f "Discharge Air Temp" @e:AHU-1 "°F" 54.6°F M M
@p:5f22 "Zone Temp"          @e:VAV-204 "°F" 71.2°F M M
… 212 more rows
{
  "meta": { "ver": "3.0" },
  "cols": [{ "name": "id" }, { "name": "curVal" }],
  "rows": [{ "id": "r:p:1a4f Discharge Air Temp",
    "curVal": "n:54.6 °F", "sensor": "m:" }]
}
05 DRIVERS

Protocol
isolation

one process per driver · gRPC over unix sockets · independent restart

BACnet

flagship
IP discovery · targeted scan · RPM read · wraps bacnet-stack
discoverread · RPMCOV: plannedguarded writes: design path

Modbus

TCP v0 · template-driven register maps
readblock-coalescetemplatesRTU / writes: planned

MQTT

planned · south ingest / north publish
subscribepublishtopic-map

OPC-UA

planned
browsereadsubscribe
06 HARDWARE

Pi-class
budget

local storage · offline operation · static core binary

MetricTargetDesign basis
Idle RAM< 150 MBPi 4-class edge host
Point load2–5k @ 15 ssubscription-first, poll fallback
Cold start< 3 ssingle Go core daemon
Core binary20–40 MBstatic core; native protocol drivers isolated
StoragelocalSQLite registry → Parquet historian
SPEC

Operating constraints

Deploymentoffline / air-gapped, first class · no telemetry
ModelHaystack-native — not an export step
Isolationone process per protocol · crash alone, restart alone
Network scopelocal L2 broadcast discovery · targeted unicast for known remote devices
FAQ

Operational
details

Does Sondwave write to controllers?

Not in the current release. A future write path is capability-gated per point, disabled unless explicitly configured, priority-scoped, and audited.

Does a scan discover every controller on a site?

No. Local BACnet broadcast discovery is limited to its Layer-2 segment. Known remote devices can be targeted over a routed path; unknown remote broadcast domains need BBMD or Foreign Device support, which is not shipped.

for integrators & OEMs

API-first
northbound

REST · WebSocket · OpenAPI · token authentication

GET /v1 — sondwave northbound
$ curl -H "Authorization: Bearer $TOKEN" edge.local/v1/devices
{ "id":"@d:AHU-1", "proto":"bacnet", "net":1, "points":40, "status":"ok", "latencyMs":12 }

$ websocat wss://edge.local/v1/ws
 { "ev":"i-am",   "dev":"@d:VAV-204", "ms":47 }
 { "ev":"cur",    "pt":"@p:1a4f",  "val":54.6 }
 { "ev":"tagged", "pt":"@p:1a4f",  "conf":0.93 }
$ sondwaved --iface eth0

Know what responded.
Know what didn't.

Inspect discovery Inspect export