bacnet-ip-rest-client
An async Python client for the BACnet/IP REST proxy. It is built on httpx.
from bacnet_ip_rest_client import Client, ProxyError
async with Client("https://bacnet-proxy.example.net", token) as client:
for obj in await client.list_objects("my-device"):
print(obj.objid, obj.name, obj.access)
temp = await client.read_property("my-device", "analog-input,1", "present-value")
slots = await client.read_property("my-device", "analog-value,5", "priority-array")
await client.write_property("my-device", "analog-value,5", "present-value", 21.5, priority=10)
await client.write_property("my-device", "analog-value,5", "present-value", None, priority=10) # relinquish
Authentication
Every request goes through the proxy's
authentication and authorization.
Pass token to Client to send it as Authorization: Bearer <token>. The
token can be one of the opaque tokens configured on the proxy, or a JWT it
accepts, such as a user's OIDC access token. Without a token, the proxy
only allows a request if its rules grant access without one, for example
by the client's IP address. A request the proxy denies raises
UnauthorizedError or ForbiddenError.
Relationship to bacpypes3
Client has the same role as a bacpypes3 Application, and
read_property() and write_property() take bacpypes3's arguments, with
some exceptions. It doesn't try to hide the ways an HTTP proxy works
differently from a BACnet/IP stack:
| bacpypes3 | this client | |
|---|---|---|
| Addressing a device | BACnet Address |
the proxy's device id: a configured alias, or a hostname/IP[:port] |
| Object identifiers | ObjectIdentifier with an ObjectType enum |
ObjectIdentifier(type: str, instance: int), also a 2-tuple; parses "analog-value,1" |
| Values | decoded into the property's BACnet datatype | JSON as the proxy sends it: enumerations as numbers, bit strings as lists of bools. REAL properties of analog objects are always float, including NaN/±Infinity |
| Errors | ErrorPDU/RejectPDU/AbortPDU, which derive from BaseException, and are sometimes returned instead of raised |
always raised, all derived from ProxyError(Exception), see below |
| Object discovery | read object-list, then each object's properties |
list_objects(): the proxy's cached catalog with names, units and access, in one request |
| ReadPropertyMultiple | one request, one transaction | none. read_properties() sends concurrent single reads, each with its own result |
| WriteProperty with array index | supported | not supported by the proxy |
| Authorization | none | a bearer token per Client. The proxy's rules decide what it may read and write (ObjectSummary.access) |
Errors
| Exception | Cause | Retried |
|---|---|---|
CommunicationError |
proxy unreachable, or a reply that couldn't be decoded | yes |
BadRequestError |
400, malformed request | no |
UnauthorizedError |
401, token not accepted | no |
ForbiddenError |
403, the proxy's authorization denies the request | no |
NotFoundError |
404, unknown device, object or property | no |
ValueRejectedError |
422, the device rejected the written value | no |
BACnetError |
502, BACnet Error/Reject/Abort from the device; error_class/error_code hold its numeric Error_Class/Error_Code |
yes, except unknown-object/unknown-property |
BACnetTimeoutError |
504, the device didn't answer | yes |
ProxyStatusError.is_unknown_object_or_property is true when the proxy
reports a missing object or property, whether it does so as a 404 or as a
502 from the device. Code that probes for optional properties, such as
priority-array, can check this one attribute.
Retries use exponential backoff as configured by RetryPolicy (default:
5 attempts, 1s doubling to at most 8s). Retry warnings are logged to the
bacnet_ip_rest_client logger. Writes are retried too, since writing the
same value at the same priority again has no further effect.
concurrency (default 10) caps the number of requests one Client has in
flight. The proxy serializes traffic to the device itself; this cap only
keeps a large read_properties() from opening hundreds of connections to
the proxy.
Development
uv run pytest
Metadata
Release files for bacnet-ip-rest-client 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| bacnet_ip_rest_client-1.0.1.tar.gz | 54.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bacnet_ip_rest_client-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 67.4 kB
Release files / bacnet_ip_rest_client-1.0.1.tar.gz
| Download URL | bacnet_ip_rest_client-1.0.1.tar.gz |
|---|---|
| Size | 54.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
633fff1f182182702aa3ca57f42b62031ab98de30c7cb703180ed45b966675ee
|
|
BLAKE2b-256 checksum How to use checksums |
1475b443b095e75ca3bb1496bf0d9a393b018efebe9641a21bb4ea33b9575937
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / bacnet_ip_rest_client-1.0.1-py3-none-any.whl
| Download URL | bacnet_ip_rest_client-1.0.1-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fe8a8107a986a1ce061857af2052ce5a9edc5f93026f7e78a30a3a505b6fe36b
|
|
BLAKE2b-256 checksum How to use checksums |
cd5cbf1afa4763cd680c7b5b0a70138a647cbf119f77c6005872dd330e6582e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logSecurity for bacnet-ip-rest-client 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for bacnet_ip_rest_client-1.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.