Summary
If a request targets a UDP port that is not in the gateway's configured Port Range, the transport drops
the datagram with no log — but the APDU timer has already been armed, so the caller gets ERR_TIMEOUT
after the full apduTimeout with nothing on the wire.
That failure signature ("timeout, but Wireshark shows we never sent anything") is very hard to diagnose
from the outside. It came up as a candidate cause while investigating #49; it was not the cause there,
but it is a real bug.
Detail
resources/node-bacstack-ts/dist/lib/transport.js:51-56:
let serverExists = Object.keys(this.serverList).findIndex((existingPort) => port.toString() == existingPort);
if (serverExists !== -1) {
let server = this.serverList[port];
server.send(buffer, 0, offset, port, address);
}
// no else — silent drop
serverList is keyed by the ports expanded from the gateway's Port Range matrix
(common.js:99-111). The device port comes from the I-Am source port
(bacnet_device.js:97, via client.js:420), so any device that responds from a port outside the
configured range is permanently unreachable and silent about it.
Meanwhile readProperty (and every other service method) calls _addCallback immediately after
sendBvlc, which arms a setTimeout for apduTimeout (client.js:193-206). Nothing checks whether
the send actually happened.
Verified
Instrumenting the transport and dgram boundaries, with portRangeMatrix: [47808]:
device port 47808 -> MATCH=true dgram.send 17 bytes -> ERR_TIMEOUT (no device present)
device port 47809 -> MATCH=false no dgram.send -> ERR_TIMEOUT
Identical caller-visible outcome, completely different cause.
Proposed fix
- Log on the drop:
Cannot send to <address>:<port> — port not in configured Port Range [<bound ports>].
This alone turns an unexplainable timeout into a one-line diagnosis.
- Have
Transport.send report failure to its caller (return value or throw) so the service methods can
fail the request immediately rather than waiting out apduTimeout.
- Consider surfacing it in the gateway node status, since it is a configuration error rather than a
network fault.
Acceptance criteria
- A request to a port outside the configured Port Range produces a log line naming the target port and
the bound ports.
- The caller's callback fires promptly with a distinguishable error, not
ERR_TIMEOUT after the full
APDU timeout.
Summary
If a request targets a UDP port that is not in the gateway's configured Port Range, the transport drops
the datagram with no log — but the APDU timer has already been armed, so the caller gets
ERR_TIMEOUTafter the full
apduTimeoutwith nothing on the wire.That failure signature ("timeout, but Wireshark shows we never sent anything") is very hard to diagnose
from the outside. It came up as a candidate cause while investigating #49; it was not the cause there,
but it is a real bug.
Detail
resources/node-bacstack-ts/dist/lib/transport.js:51-56:serverListis keyed by the ports expanded from the gateway's Port Range matrix(
common.js:99-111). The device port comes from the I-Am source port(
bacnet_device.js:97, viaclient.js:420), so any device that responds from a port outside theconfigured range is permanently unreachable and silent about it.
Meanwhile
readProperty(and every other service method) calls_addCallbackimmediately aftersendBvlc, which arms asetTimeoutforapduTimeout(client.js:193-206). Nothing checks whetherthe send actually happened.
Verified
Instrumenting the transport and dgram boundaries, with
portRangeMatrix: [47808]:Identical caller-visible outcome, completely different cause.
Proposed fix
Cannot send to <address>:<port> — port not in configured Port Range [<bound ports>].This alone turns an unexplainable timeout into a one-line diagnosis.
Transport.sendreport failure to its caller (return value or throw) so the service methods canfail the request immediately rather than waiting out
apduTimeout.network fault.
Acceptance criteria
the bound ports.
ERR_TIMEOUTafter the fullAPDU timeout.