Bridges field meters behind controllers like Siemens Desigo PXC5/PXC7 to LibreNMS over BACnet/IP. Includes custom OS detection, auto-discovery, and service checks For Monitoring. Pure Python 3 stdlib — no pip dependencies.
Your power, water, and steam meters communicate with a Siemens PXC station via Modbus RTU (serial). Since the meters do not have their own IP addresses, they cannot communicate directly with LibreNMS. The objective is to integrate these meters into LibreNMS to monitor their uptime, analyze device logs and device states, and visualize historical data through graphs, similar to the example below.
BACNET OK - BUILDING3-ELEC-1F-M33 = 1 (Operational)
Why this project exists:
- SNMP is a dead end on PXC firmware. A full walk proves the agent serves only the MIB-II
systemgroup — no interfaces, no CPU/memory, no traps, no enterprise OIDs. SNMP is only good for basic up/down status. - Modbus TCP is not offered. Port 502 is refused. The PXC is a Modbus master — it polls the meters over its COM ports, and each meter's state lives as a BACnet object on the owning station.
- BACnet/IP works. Unicast
ReadPropertyto UDP 47808 works across subnets with no BBMD required. There is no need for the certificate-secured BACnet/SC (wss://) hub the ABT server uses.
Reference: Siemens Desigo PXC5.E24 documentation (SID)
[ Modbus meters ] --serial COM--> [ Siemens PXC5.E24 / PXC7 ] --BACnet/IP UDP 47808--> [ LibreNMS server ]
M33, M34, ... sBix_01..sBix_04, inst 1-4 check_bacnet services
| |
Multistate 'PrphDev' objects Services + graphs + alerts
1 = Operational, 4 = Device missing
Each meter appears on its station as a BACnet multi-state-value named e.g. BUILDING3'sBix_04'BUILDING3-ELEC-1F-M33'PrphDev. This project reads present-value + state-text and turns it into a LibreNMS service check.
| Device | Model | BACnet Instance | Answers BACnet/IP? | Status |
|---|---|---|---|---|
| sBix_01 | PXC7.E400L | 1 | Yes | Production |
| sBix_02 | PXC5.E24 | 2 | Pending | SC hub role / halted program |
| sBix_03 | PXC5.E24 | 3 | Yes | Production |
| sBix_04 | PXC5.E24 | 4 | Yes | Production |
Meter state numbering (confirmed live): 1 = Operational, 4 = Device missing, plus 8 additional states — descriptive text is served directly by the controller.
Custom OS detection identifies the Siemens Desigo PXC platform, while real-time service badges track downstream Modbus meter states:
Every peripheral meter reports directly into LibreNMS with native state translation (1 = Operational, 4 = Device missing):
Full audit trail tracking when field meters drop offline or recover after wiring/maintenance fixes:
AI-Driven Dashboard (Work in Progress)
More than just a data visualization tool, it analyzes system data, identifies potential issues, and generates alerts to help you take proactive action.

check_bacnet Nagios-style plugin executed by LibreNMS (BACnet/IP unicast ReadProperty)
bacnet_discover Inventory a station: walks object-list, lists multistate values + states
bacnet2librenms Scan + auto-create LibreNMS services via API (idempotent)
resources/definitions/os_detection/desigo-pxc.yaml LibreNMS custom OS detection definition
resources/definitions/os_discovery/desigo-pxc.yaml LibreNMS model/serial/version discovery + state sensors
mibs/siemens/ SIEMENS-SMI, AUTOMATION-SMI, AUTOMATION-TC, AUTOMATION-SYSTEM-MIB
assets/banner.jpg Social banner image
assets/logo.jpg Square project logo
assets/librenms-overview.png Production overview dashboard screenshot
assets/librenms-services.png Services status table screenshot
assets/librenms-eventlog.png State transition event log screenshot
assets/topology-view.png topology dashboard screenshot
plugins/ldp-api.php
plugins/topology-multi.html
All three scripts must live together in the same directory — bacnet_discover and bacnet2librenms import check_bacnet. Pure Python 3 standard library only.
-
LibreNMS server with target controller devices already added via SNMP
-
Network access via UDP 47808 from LibreNMS poller to each PXC station
-
LibreNMS API token (Web UI → Settings gear → API → API Settings)
-
On the LibreNMS server:
rootfor installation,librenmssystem user for service checks -
BAS engineering access to confirm BACnet/IP is enabled and verify device instance numbers
Without this, PXC7 reports a generic net-snmp sysObjectID .1.3.6.1.4.1.8072.3.2.10, causing LibreNMS to display the OS as generic "Linux".
- Verify the Automation MIB from the LibreNMS server:
snmpwalk -v2c -c <community> <target-ip> .1.3.6.1.4.1.4329If empty, enable SNMP "extended / Automation MIB" in ABT Site → Device Settings → SNMP and re-test. The OS package includes fallback detection if extended MIBs cannot be enabled.
- Deploy definitions and MIBs (adjust
/opt/librenmspath if needed):
scp resources/definitions/os_detection/desigo-pxc.yaml root@<librenms-ip>:/opt/librenms/resources/definitions/os_detection/
scp resources/definitions/os_discovery/desigo-pxc.yaml root@<librenms-ip>:/opt/librenms/resources/definitions/os_discovery/
scp mibs/siemens/* root@<librenms-ip>:/opt/librenms/mibs/siemens/
ssh root@<librenms-ip> "chown -R librenms:librenms \
/opt/librenms/resources/definitions/os_detection/desigo-pxc.yaml \
/opt/librenms/resources/definitions/os_discovery/desigo-pxc.yaml \
/opt/librenms/mibs/siemens/"(For older LibreNMS directory structures, place YAMLs under includes/definitions/desigo-pxc.yaml and includes/definitions/discovery/desigo-pxc.yaml).
- Clear discovery cache and rediscover:
su - librenms
lnms config:clear
lnms device:discover <target-ip>- Verify in LibreNMS: The device overview should show OS as Siemens Desigo PXC, hardware model, and firmware version. Health sensors will populate under the State tab.
- Copy the plugin scripts into your Nagios plugins directory:
sudo cp check_bacnet bacnet_discover bacnet2librenms /usr/lib/nagios/plugins/
sudo chmod 755 /usr/lib/nagios/plugins/check_bacnet /usr/lib/nagios/plugins/bacnet_discover /usr/lib/nagios/plugins/bacnet2librenms- Enable service monitoring in LibreNMS:
su - librenms
lnms config:set show_services true
lnms config:set discover_services true
lnms config:set nagios_plugins /usr/lib/nagios/plugins- Ensure cron-based polling is active (skip if running the systemd dispatcher):
echo '*/5 * * * * librenms /opt/librenms/services-wrapper.py 1' | sudo tee /etc/cron.d/librenms-services- Test execution as the
librenmsuser:
sudo -u librenms /usr/lib/nagios/plugins/check_bacnet -H <target-ip> -i <instance-number>
# Output: BACNET OK - operational [sBix_01 PXC7.E400L 02.22.233.20] | status=0;;;0;5Check overall controller health (system-status = operational):
./check_bacnet -H 192.168.1.11 -i 1Monitor Modbus peripheral meter status:
./check_bacnet -H 192.168.1.14 -i 4 -o msv:33 -l BUILDING3-ELEC-1F-M33 --state-text --ok-states 1
# BACNET OK - BUILDING3-ELEC-1F-M33 = 1 (Operational) | 'BUILDING3-ELEC-1F-M33'=1;;;Monitor analog points (kWh, flow rates, temperature) with warning/critical thresholds and performance graphing:
./check_bacnet -H <ip> -i <instance> -o av:<n> -u kWh -l 5F_DB2_kWh -w 10000 -c 20000Common Flags:
-
-o type:instance: Target object (ai,ao,av,bi,bo,bv,msi,mso,msv,device) -
-r property: Property ID (defaults topresent-value; e.g.,reliability) -
-w/-c: Warning / Critical thresholds (valueormin:max) -
--state-text: Query and output the controller's human-readable state string -
--ok-states: Comma-separated list of healthy numeric states (overrides-w/-c) -
-u: Unit label for graphing perfdata
Inspect all objects configured on a station and extract ready-to-use LibreNMS parameters:
./bacnet_discover -H 192.168.1.13 -i 3
./bacnet_discover -H 192.168.1.13 -i 3 --types msv,av,ai --filter consumptionAutomatically discover and register services in LibreNMS via API (safe and idempotent):
export LIBRENMS_TOKEN="<your_api_token>"
./bacnet2librenms -H 192.168.1.13 -i 3 # Dry run preview
./bacnet2librenms -H 192.168.1.13 -i 3 --apply # Commit changes to LibreNMSConfigure a service alert rule in LibreNMS:
services.service_status != 0Field Tip: When setting up a new plant, add your services first and allow technicians to correct physical Modbus daisy-chain wiring and addressing before enabling notification dispatchers.
The Multi-Topology View Dashboard is a read-only monitoring interface that analyzes and visualizes meter states, identifies potential issues, and highlights devices that require attention.
Upload the following files to /opt/librenms/html/plugins:
plugins/topology-multi.htmlplugins/ldp-api.php
Create a dedicated read-only LibreNMS user, generate an API token, and configure it exclusively in the LDP_API_TOKEN variable inside ldp-api.php on the server.
Security: The API token never leaves the server. PHP handles API requests, and the browser receives only the required JSON meter data.
Access the dashboard:
http://yournms.com/plugins/topology-multi.html
The dashboard automatically builds a Needs Attention panel at the top of the page on every refresh. It analyzes the latest 500 log entries per controller to identify meters that require investigation.
1. Flapping Meters
- Detects meters with 4 or more state transitions (
FLAP_MIN), indicating unstable connectivity or intermittent communication. - Displays an amber ⚡ badge with the transition count to distinguish flapping meters from permanently down devices.
- Example:
6 transitions — Flapping, not a dead meter. Check Modbus tap/terminator. - Meters such as
UB1-GAS-BOILER-M03will automatically appear in this section when they meet the threshold.
2. Down Now
- Identifies meters that are currently in a critical state.
- Sorts them by the longest down duration, placing devices that have been down the longest at the top for prioritization.
Every item in the Needs Attention panel is clickable and opens the corresponding meter's inspector drawer for further investigation.
The dashboard provides additional visibility into individual meter conditions:
- Flapping Badge: An amber
⚡×6badge appears on flapping meter cards alongside the existingOKorCRITICALstatus indicator. - Transition Details: Each meter's inspector drawer includes a Transitions row, showing the number of state changes detected in the available logs and whether the meter is flapping.
The following parameters are available in the configuration block of ldp-api.php:
| Parameter | Default | Description |
|---|---|---|
FLAP_MIN |
4 |
Minimum state transitions required to classify a meter as flapping. |
EVENTLOG_LIMIT |
500 |
Number of recent log entries per controller to analyze. |
Adjust these values according to your monitoring requirements:
- Earlier Warning: Reduce
FLAP_MINto3to detect intermittent issues sooner, particularly on quieter Modbus buses. - Extended Lookback: Increase
EVENTLOG_LIMITto2000to analyze a longer history. This may slightly increase dashboard refresh time.
Device IP addresses are included in the source code. Since these are internal plant network addresses and are essential to the dashboard's purpose, this is acceptable within the intended environment.
However, the dashboard itself is currently unauthenticated. Anyone who can access its URL can view the meter states and related information.
If the dashboard is restricted to the internal plant network, this may be acceptable. If broader access is required, implement one of the following security measures:
- Nginx IP Restriction: Configure an allowlist for authorized internal IP ranges, such as
10.x.x.xor172.31.x.x, followed by adeny allrule for the dashboard path. - Shared-Password Gate: Configure a password-protected access layer at the Nginx reverse proxy level.
Restrict access before exposing the dashboard beyond the trusted plant network.
-
Controller Silent on UDP 47808: If a station does not reply despite BACnet/IP being enabled, check if the station is acting exclusively as a BACnet/SC hub or has an unstarted/halted application program in the ABT Site runtime.
-
Energy / Flow Performance Data: Discover analog objects with
./bacnet_discover -H <ip> -i <inst> --types av,ai --filter energy. Adding them as plain services allows LibreNMS to build long-term RRD utilization graphs. -
OS Recognition Fallback: If LibreNMS still shows "Linux", run:
php /opt/librenms/discovery.php -h <target-ip> -d -m core
lnms config:clearWe are actively expanding LibreDesigoPulse to support more building automation controllers, specialized MIBs, and expanded protocol features. Contributions are very welcome!
- Expanded Hardware Testing: Add verification profiles for additional controller series (e.g., Siemens PXC4, PXX, Desigo CC integrations, Schneider Electric, Honeywell, Johnson Controls).
- BACnet/SC Support: Experimental support for secure connect hubs (
wss://). - Write Capability: Safe diagnostic overrides for digital points.
- LibreNMS Upstream Submission: Package the YAML OS definitions for direct upstream inclusion in the main LibreNMS repository.
- Custom Map to Display Services: Live plant/floor map dashboard showing meter service states (e.g., LibreNMS availability map / custom widget with per-meter OK / warning / critical tiles).
- Option A (built-in, fastest): LibreNMS availability map — services were created with
name = <meter label>precisely so each tile maps 1:1 to a meter; group by device (sBix_01..sBix_04) for a per-building view. - Option B (custom floor plan): Small HTML/JS widget over a plant image, polling
GET /api/v0/services/<device>with the API token and coloring each meter marker byservice_status(0 OK / 1 warning / 2 critical). Refresh every 60–300 s; link each marker to its service page.
- Option A (built-in, fastest): LibreNMS availability map — services were created with
- Report Tested Hardware: Add your verified controller model, firmware revision, and object mapping patterns to the Verified Hardware table via a pull request.
- Submit PRs: Keep all core monitoring scripts dependency-free (standard library only) so pollers remain lightweight.
- Open Issues: Share edge cases, unusual BACnet encodings, or vendor-specific multistate value maps.
This project is licensed under the MIT License — free to use, modify, and integrate into enterprise network operations.


