Proprietary Objects
Some manufacturers provide special variables inside their controllers in the form of proprietary objects or expand standard objects with proprietary properties. BAC0 supports both via two complementary approaches:
1) Numeric IDs (no imports)
Use numeric object and property identifiers directly in a request string:
@obj_142means a proprietary object type with ID 142@prop_1032means a proprietary property identifier 1032
Examples:
await bacnet.read('2:5 @obj_142 1 @prop_1032')
await bacnet.readMultiple('2:5 @obj_142 1 objectName @prop_1032')
2) Class-based registration (import vendor classes)
bacpypes3 uses real Python classes to define vendor extensions. Importing these classes registers the vendor information and enables named properties and objects. BAC0 re-exports known vendor classes for convenience. Import once at startup and bacpypes3 will “know what to do.”
See: Proprietary objects with bacpypes3
Quick examples:
# Johnson Controls (vendor_id 5)
from BAC0.core.proprietary_objects import JCIDeviceObject
dev = await BAC0.device('2:5', 5005, bacnet)
val = await dev.read_property('supervisory_device_online')
# Produal (vendor_id 783) proprietary object names
from BAC0.core.proprietary_objects import Produal783Config1
temp_sp_ll = await dev.read_property(('CONFIG1', 1, 'TEMPSP_LL'))
Writing to proprietary properties
When writing to a proprietary property with the raw string API you may see
errors like TypeError: issubclass() arg 1 must be a class if bacpypes3
doesn’t know how to encode the value. You must import the vendor classes so
bacpypes3 knows the datatype and encoding for that proprietary property. Vendor
context alone with numeric IDs is not sufficient.
Examples:
# Via a device instance (vendor classes have been imported; vendor_id is passed automatically)
await dev.write_property(('device', 5005, 'supervisory_device_online'), True)
# Raw string syntax with numeric IDs (vendor classes must be imported)
await bacnet._write('2:5 device 5005 3653 true', vendor_id=5)
Register vendor classes (bacpypes3 style)
No dynamic class creation is needed. Simply import the vendor modules exposed by BAC0; the import registers everything:
from BAC0.core.proprietary_objects import (
JCIDeviceObject, # vendor_id 5
PrivaBVDeviceObject, # vendor_id 105
Produal651Config, # vendor_id 651
Produal783Config1, Produal783Config2, # vendor_id 783
)
Proprietary objects
Read by numeric IDs or by names (after import):
# Numeric
await bacnet.read('2:5 140 1 objectName')
await bacnet.readMultiple('2:5 140 1 all')
# Named (after importing vendor classes)
name = await dev.read_property(('CONFIG1', 1, 'objectName'))
Proprietary properties
Examples on a JCI device (vendor_id 5):
# Named (after import)
model = await dev.read_property(('device', 5005, 'pcode'))
await dev.write_property(('device', 5005, 'supervisory_device_online'), True)
Vendor context for reads and writes
- bacpypes3 resolves vendor context from the device info cache. On first
contact, BAC0 populates this cache (Who-Is/I-Am), so subsequent reads/writes use the correct VendorInfo automatically.
- When you use
BAC0.device(...), the device’s vendor_id is known and passed through; you don’t need to specify it.
- When you use
- With the raw string API, you usually don’t need to pass
vendor_ideither, because the device_info_cache provides it. Supplying
vendor_id=<id>is an optional fallback if the cache hasn’t been populated yet.
- With the raw string API, you usually don’t need to pass
- Proprietary writes still require importing the vendor classes so bacpypes3
knows the datatypes and encodings; vendor context alone isn’t enough.
Can proprietary objects be added to BAC0.device points?
Not currently. BAC0 “points” map to presentValue-focused objects and metadata used by BAC0, which doesn’t generalize to arbitrary proprietary objects. Interact with proprietary objects directly via reads/writes as shown above.
How to implement readMultiple with proprietary objects and properties
Use the @obj_ and @prop_ syntax when composing requests:
await bacnet.readMultiple('2000:31 device 5012 @prop_3653 analogInput 1106 presentValue units')
How to find proprietary objects and properties
For a device or a point, list all properties:
props = await device.bacnet_properties()
# or
props = await point.bacnet_properties()
This is equivalent to bacnet.readMultiple('addr object id all').
Note
The values are cached. If the device changes and you need fresh data, refresh first, then read again:
await device.update_bacnet_properties()
props = await device.bacnet_properties()
For points:
await point.update_bacnet_properties()
props = await point.bacnet_properties()