A Python-based Prometheus exporter for BACnet (Building Automation and Control Networks) devices. This exporter collects metrics from BACnet devices and exposes them in Prometheus format for monitoring and alerting.
- Connect to BACnet/IP devices and read properties
- Expose BACnet metrics in Prometheus format
- Support for automatic device discovery
- Configurable via JSON/YAML files or environment variables
- Health check endpoint
- Support for various BACnet object types:
- Analog Input/Output/Value
- Binary Input/Output/Value
- Multi-state Input/Output
- Device objects
# Clone the repository
git clone https://github.com/yourusername/bacnet-exporter.git
cd bacnet-exporter
# Install dependencies
pip install -r requirements.txt- Python 3.8+
- bacpypes >= 0.20.0
- prometheus-client >= 0.19.0
- pydantic >= 2.0.0
Run the exporter with default settings:
python -m bacnet_exporter.exporterMetrics will be available at http://localhost:8080/metrics
Create a configuration file (config.json):
{
"bacnet_broadcast_address": "255.255.255.255",
"bacnet_port": 47808,
"bacnet_timeout": 5.0,
"prometheus_host": "0.0.0.0",
"prometheus_port": 8080,
"scrape_interval": 15,
"auto_discover": true,
"log_level": "INFO",
"devices": [
{
"device_id": 1,
"ip_address": "192.168.1.100",
"port": 47808,
"name": "HVAC Controller",
"objects": [
{
"object_type": "analog-input",
"object_instance": 0,
"properties": ["present-value", "reliability"]
},
{
"object_type": "binary-input",
"object_instance": 0,
"properties": ["present-value"]
}
]
}
]
}Run with the configuration file:
python -m bacnet_exporter.exporter --config config.jsonexport BACNET_BROADCAST_ADDRESS=255.255.255.255
export BACNET_PORT=47808
export PROMETHEUS_PORT=9090
export SCRAPE_INTERVAL=30
export AUTO_DISCOVER=true
export LOG_LEVEL=DEBUG
python -m bacnet_exporter.exporter| Variable | Default | Description |
|---|---|---|
BACNET_BROADCAST_ADDRESS |
255.255.255.255 |
BACnet broadcast address for device discovery |
BACNET_PORT |
47808 |
BACnet port (default for BACnet/IP) |
BACNET_TIMEOUT |
5.0 |
Timeout for BACnet operations in seconds |
BACNET_LOCAL_DEVICE_IP |
- | Local device IP address (optional) |
PROMETHEUS_HOST |
0.0.0.0 |
Host to bind the Prometheus metrics server |
PROMETHEUS_PORT |
8080 |
Port to expose Prometheus metrics |
PROMETHEUS_METRICS_PATH |
/metrics |
Path for Prometheus metrics endpoint |
SCRAPE_INTERVAL |
15 |
Interval between scrapes in seconds |
SCRAPE_TIMEOUT |
10 |
Timeout for each scrape in seconds |
AUTO_DISCOVER |
false |
Enable automatic device discovery |
LOG_LEVEL |
INFO |
Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
{
"bacnet_broadcast_address": "255.255.255.255",
"bacnet_port": 47808,
"bacnet_timeout": 5.0,
"bacnet_local_device_ip": null,
"prometheus_host": "0.0.0.0",
"prometheus_port": 8080,
"prometheus_metrics_path": "/metrics",
"scrape_interval": 15,
"scrape_timeout": 10,
"auto_discover": false,
"log_level": "INFO",
"devices": [
{
"device_id": 1,
"ip_address": "192.168.1.100",
"port": 47808,
"name": "Device Name",
"objects": [
{
"object_type": "analog-input",
"object_instance": 0,
"properties": ["present-value", "reliability", "status-flags"]
}
]
}
]
}Add the exporter to your Prometheus prometheus.yml:
scrape_configs:
- job_name: 'bacnet'
static_configs:
- targets: ['localhost:8080']
scrape_interval: 15sbacnet_exporter_scrape_duration_seconds- Duration of BACnet scrapebacnet_exporter_scrape_total- Total number of scrapes performedbacnet_exporter_scrape_errors_total- Total number of scrape errorsbacnet_exporter_objects_total- Total number of BACnet objects being monitoredbacnet_exporter_devices_total- Total number of BACnet devices being monitoredbacnet_connection_active- Whether BACnet connection is active (1=active, 0=inactive)
bacnet_object_present_value- Present value of BACnet objectbacnet_object_reliability- Reliability status of BACnet objectbacnet_object_status_flags- Status flags of BACnet objectbacnet_object_event_state- Event state of BACnet object
bacnet_device_info- Information about BACnet devices (Info type metric)
All object metrics have the following labels:
device_id- BACnet device IDobject_name- Object nameobject_type- Object type (e.g., analog-input)object_instance- Object instance number
| Object Type | Description |
|---|---|
analog-input |
Analog input values (temperature, humidity, etc.) |
analog-output |
Analog output values (setpoints, control values) |
analog-value |
Generic analog values |
binary-input |
Binary input values (on/off, open/closed) |
binary-output |
Binary output values (relay states) |
binary-value |
Generic binary values |
multi-state-input |
Multi-state input values |
multi-state-output |
Multi-state output values |
device |
Device information |
| Property | Description |
|---|---|
present-value |
Current value of the object |
reliability |
Reliability status of the value |
status-flags |
Status flags (fault, override, etc.) |
event-state |
Current event state |
engineer-units |
Engineering units for the value |
description |
Object description |
object-name |
Object name |
usage: exporter.py [-h] [-c CONFIG] [-v] [--version]
BACnet Prometheus Exporter
options:
-h, --help show this help message and exit
-c CONFIG, --config CONFIG
Path to configuration file (JSON or YAML)
-v, --verbose Enable verbose logging
--version show program's version number and exit
| Endpoint | Description |
|---|---|
/metrics |
Prometheus metrics in text format |
/health |
Health check endpoint (returns {"status": "healthy"}) |
/ |
Simple HTML page with links to metrics and health |
- Ensure the BACnet devices are on the same network
- Check that port 47808 is not blocked by a firewall
- Verify the broadcast address is correct for your network
- Check the exporter logs for errors
- Verify the device IDs and object types are correct
- Use
--verboseflag for detailed logging
- Ensure
AUTO_DISCOVER=trueis set - Check that the broadcast address is correct
- Some networks may require a specific subnet broadcast address
MIT License