OPC UA · BMS · DESIGO CC · Beckhoff · asyncua · MQTT PubSub · 11 min read

OPC UA in Building Automation: BMS Integration, Data Logging and KPIs

OPC UA has become the integration backbone for modern intelligent buildings, providing a single, vendor-neutral interface that connects BMS controllers, energy meters, HVAC equipment, and cloud analytics platforms. Unlike BACnet or Modbus, OPC UA embeds security and a self-describing information model — meaning an energy management system can discover all available data points from a DESIGO CC or TwinCAT server without requiring a separate register map or point list.

Role of OPC UA in buildings

A typical commercial building integrates three or more subsystems that historically used incompatible protocols: a BACnet/IP BMS for HVAC and access control, Modbus RTU energy meters on a serial bus, and a CMMS (Computerised Maintenance Management System) for equipment service records. OPC UA acts as the horizontal integration layer, providing a unified read/write/subscribe interface across all subsystems from a single client connection.

The OPC UA server sits between field protocols and the IT layer. It polls or subscribes to data from BACnet, Modbus, and KNX subsystems using protocol-specific drivers, then exposes all data in a single browsable address space. Clients — SCADA systems, energy management platforms, dashboards, and cloud connectors — connect to the OPC UA server once and access all building data through a standard API, regardless of the underlying protocol.

Building OPC UA integration topology

Field layer (field protocols)
  BACnet/IP: Siemens PXC200, Distech EC-Net controllers
  Modbus TCP: Schneider PM5xxx energy meters, Janitza UMG 96
  KNX/IP: WEINZIERL KNX IP Interface 731
  M-Bus: heat meters, gas meters (IEC 62056)

  ↓ protocol drivers (inside BMS or gateway)

OPC UA Server layer
  Siemens DESIGO CC with OPC UA server module
    └── exposes BACnet objects as OPC UA Variables
    └── exposes alarm conditions as OPC UA AlarmCondition
  Beckhoff TwinCAT OPC UA Server
    └── exposes PLC variables directly from ADS runtime
  Kepware KEPServerEX
    └── multi-protocol gateway (BACnet + Modbus → OPC UA)

  ↓ opc.tcp:// or opc.wss://

Clients (standard OPC UA)
  Energy management platform (Schneider PME, EcoStruxure)
  SCADA / MES (Ignition, WinCC OA, Aveva)
  Cloud connector (Azure IoT OPC Publisher, AWS Greengrass)
  Analytics / dashboards (Grafana OPC UA plugin, Power BI)

OPC UA server implementation options

For building automation, three OPC UA server implementations dominate. Each is suited to a different BMS ecosystem and hardware platform.

ServerPlatformProtocol driversLicense
Siemens DESIGO CC with OPC UAWindows Server, DESIGO CC application serverBACnet/IP, BACnet MS/TP, KNX, Modbus, M-Bus via DESIGO driversPaid — part of DESIGO CC license
Schneider EcoStruxure BMS OPC UAEcoStruxure Building Operation (EBO) serverBACnet/IP, Modbus, LON, M-Bus, DALIPaid — EBO license
Beckhoff TwinCAT OPC UA ServerWindows PC running TwinCAT 3 runtimeTwinCAT ADS (PLC variables), EtherCAT I/O, Modbus via PLC function blocksFree with TwinCAT license
Kepware KEPServerEXWindows PC/server (standalone gateway)BACnet/IP, Modbus RTU/TCP, OPC DA, SNMP, EtherNet/IP, 150+ driversPaid — per-driver licensing
Pro-face Remote HMI OPC UAEmbedded Linux on GP4000/GP4600 HMIModbus TCP, EtherNet/IP, Mitsubishi MC ProtocolIncluded with HMI

Beckhoff TwinCAT OPC UA Server — free for integrators: If you are using TwinCAT 3 as the PLC runtime for a building controller, the TwinCAT OPC UA Server is included at no extra cost. It exposes all PLC variables declared with {attribute 'OPC.UA.DA' := '1'} attribute directly as OPC UA nodes. This is the lowest-cost path to OPC UA in new panel-mounted building controllers.

OPC UA information model for buildings

IEC 62541-100 (OPC UA for Buildings) defines a standardised information model mapping ISO 16739-1 IFC (Industry Foundation Classes) concepts to OPC UA ObjectTypes. This allows an energy management system to navigate a building server’s address space using well-known type names — SpaceType, ZoneType, HVACSystemType — rather than vendor-specific string paths.

IEC 62541-100 building information model structure

BuildingType (ns=2;s=Building_Alpha_Tower)
├── SiteType (ns=2;s=Site_Riga_01)
│   ├── BuildingStoreyType (ns=2;s=Floor_03)
│   │   ├── SpaceType (ns=2;s=Office_3A)  ← IFC IfcSpace mapping
│   │   │   ├── AirTemperature [Variable, Float, °C]
│   │   │   ├── CO2Concentration [Variable, UInt16, ppm]
│   │   │   └── OccupancyState [Variable, Boolean]
│   │   └── SpaceType (ns=2;s=Meeting_3B)
│   └── BuildingStoreyType (ns=2;s=Floor_04)
├── HVACSystemType (ns=2;s=AHU_Main_01)  ← IFC IfcSystem mapping
│   ├── SupplyAirTemperature [Variable, Float, °C]
│   ├── ExhaustAirTemperature [Variable, Float, °C]
│   ├── HeatingCoilValve [Variable, Byte, 0–100%]
│   ├── CoolingCoilValve [Variable, Byte, 0–100%]
│   ├── FanSpeed [Variable, UInt16, RPM]
│   └── OperatingMode [Variable, Enum: Off/Auto/Heating/Cooling/Night]
└── EnergyMeterType (ns=2;s=MainMeter_kWh)  ← IEC 62056 meter
    ├── ActiveEnergyImport [Variable, Double, kWh]
    ├── ActivePower [Variable, Float, kW]
    └── Timestamp [Variable, DateTime]

Energy KPI extraction via OPC UA subscription

Energy management requires reliable, timestamped kWh readings from meter nodes. Rather than polling meters at fixed intervals (which can miss peaks and generates constant traffic), use OPC UA subscriptions with a PublishingInterval matched to your reporting granularity, and a deadband to suppress reporting on trivially small increments.

KPIOPC UA nodeRecommended intervalDeadband
Hourly kWh consumptionActiveEnergyImport (Double, kWh)PublishingInterval 60 000 msAbsolute 0.01 kWh
15-min peak demandActivePower (Float, kW)PublishingInterval 900 000 msAbsolute 0.1 kW
Real-time power monitoringActivePower (Float, kW)PublishingInterval 5 000 msPercent 1%
Daily heat meter readingThermalEnergyImport (Double, kWh th)PublishingInterval 86 400 000 msAbsolute 0.1 kWh
Gas consumptionGas_Volume (Double, m³)PublishingInterval 3 600 000 msAbsolute 0.001 m³

OPC UA PubSub: push building data to cloud MQTT broker

OPC UA PubSub (IEC 62541-14) extends the client-server model with a publish-subscribe pattern using MQTT or UDP multicast as the transport. Instead of a cloud platform polling the OPC UA server, the server pushes DataSetMessages to an MQTT broker on a configured WriterGroup PublishingInterval. This is the recommended pattern for cloud integration when the OPC UA server is behind a NAT or firewall that blocks inbound TCP 4840.

OPC UA PubSub — Kepware to MQTT broker configuration

# Kepware IoT Gateway Plugin — OPC UA PubSub to MQTT

Agent type: MQTT Client (Publisher)
Broker URL: mqtts://iot.yourdomain.com:8883
Client ID: kepware-building-01
TLS: enabled (CA cert + client cert for mutual TLS)

Published datasets (JSON encoding, UA-JSON):
  Topic: building/01/hvac/ahu01
  Payload (DataSetMessage, JSON):
  {
    "MessageId": "uuid-xxx",
    "PublisherId": "kepware-building-01",
    "DataSetWriterId": 1001,
    "Timestamp": "2025-03-14T10:30:00Z",
    "Payload": {
      "SupplyAirTemperature": { "Value": 18.4, "StatusCode": "Good", "SourceTimestamp": "..." },
      "FanSpeed":             { "Value": 1450, "StatusCode": "Good" },
      "HeatingCoilValve":     { "Value": 72,   "StatusCode": "Good" }
    }
  }

  Topic: building/01/energy/main-meter
  PublishingInterval: 60000 ms
  QueueSize: 1 (latest value only)

Python OPC UA client — asyncua example

The asyncua library (formerly opcua-asyncio) is the recommended Python OPC UA client for building automation scripting. It supports async/await, all security modes, X.509 certificates, and subscriptions. Install withpip install asyncua.

asyncua — connect, browse, read, subscribe

import asyncio
from asyncua import Client
from asyncua.crypto.security_policies import SecurityPolicyBasic256Sha256
from asyncua.ua import MessageSecurityMode

class SubHandler:
    """Callback invoked for each subscription notification."""
    def datachange_notification(self, node, val, data):
        print(f"  DataChange: {node} = {val}  status={data.monitored_item.Value.StatusCode}")

async def main():
    url = "opc.tcp://192.168.10.50:4840/freeopcua/server/"

    async with Client(url=url) as client:
        # --- Security: Sign + Encrypt, Basic256Sha256, X.509 cert ---
        await client.set_security(
            SecurityPolicyBasic256Sha256,
            certificate="client_cert.pem",
            private_key="client_key.pem",
            server_certificate="server_cert.pem",
            mode=MessageSecurityMode.SignAndEncrypt,
        )

        print("Connected. Server namespaces:")
        for i, ns in enumerate(await client.get_namespace_array()):
            print(f"  ns={i}: {ns}")

        # --- Browse Objects root ---
        objects = client.get_objects_node()
        children = await objects.get_children()
        for child in children:
            name = await child.read_browse_name()
            print(f"  Object: {name.Name}")

        # --- Read a specific variable by NodeId ---
        temp_node = client.get_node("ns=1;s=AHU_01.SupplyAirTemperature")
        temp_value = await temp_node.read_value()
        print(f"Supply air temperature: {temp_value:.1f} °C")

        # --- Read EngineeringUnits property ---
        eu = await temp_node.read_data_value()
        print(f"StatusCode: {eu.StatusCode}")

        # --- Subscribe to multiple nodes ---
        handler = SubHandler()
        subscription = await client.create_subscription(500, handler)  # 500 ms publishing
        nodes = [
            client.get_node("ns=1;s=AHU_01.SupplyAirTemperature"),
            client.get_node("ns=1;s=AHU_01.FanSpeed"),
            client.get_node("ns=1;s=Meter.kWh"),
        ]
        await subscription.subscribe_data_change(nodes)

        print("Subscribed. Waiting 30 seconds for notifications...")
        await asyncio.sleep(30)
        await subscription.delete()

asyncio.run(main())

OPC UA for HVAC: Siemens and Beckhoff examples

Two common building controller platforms expose OPC UA servers natively. Siemens DESIGO targets large commercial buildings with centralised BMS; Beckhoff TwinCAT targets panel-mounted controllers with direct I/O.

Siemens DESIGO CC OPC UA Server: Enabled via the DESIGO CC Management Platform add-on license. The server exposes all DESIGO datapoints (including BACnet objects imported from PXC controllers) as OPC UA Variables in a hierarchy matching the DESIGO management station folder structure. Default endpoint: opc.tcp://<desigo-server>:4840. Supports Sign+Encrypt with Basic256Sha256 and X.509 client certificates. Alarm and event conditions from DESIGO are exposed as OPC UA AlarmCondition nodes.

Beckhoff TwinCAT OPC UA Server (TC3 OPC UA): Free with any TwinCAT 3 runtime license. PLC variables marked with the OPC UA attribute in the STRUCTURED TEXT declaration are automatically published. Supports up to 5000 monitored items at 10 ms SamplingInterval on an IPC with a standard processor. The DESIGO RXB room controller series also includes an embedded OPC UA server (port 48040 by default) with direct access to room temperature, setpoint, fan coil valve, and presence detector state.

Security hardening for building OPC UA servers

Building OPC UA servers are IT/OT convergence points and are high-value targets. Apply the following hardening steps during commissioning:

Hardening stepConfiguration action
Disable Anonymous authRemove AnonymousIdentityToken from endpoint configuration; enforce Username or X.509
Disable deprecated security policiesRemove Basic128Rsa15 and Basic256 endpoints; enable only Basic256Sha256 and Aes256Sha256RsaPss
Enforce Sign+EncryptSet minimum MessageSecurityMode = SignAndEncrypt on all production endpoints
Certificate trust listImport only known client certificates into the server trust list; reject all others
Audit trailEnable OPC UA audit events (AuditActivateSessionEvent, AuditWriteUpdateEvent); forward to SIEM
Firewall rulesAllow inbound TCP 4840 only from known client IP addresses on the OT VLAN; block from IT LAN
Certificate expiry monitoringSet up alerting when server or client certs approach expiry (90-day warning)
TwinCAT: read-only namespaceDeclare monitoring variables as VAR_OUTPUT or use UA role to restrict writes

IEC 62443-3-3 Security Level 2 requirement: For buildings subject to EN 50159 (rail) or ISO 27001 BMS scope, IEC 62443-3-3 SL-2 requires that all remote management connections use X.509 certificate-based mutual authentication. Anonymous and username-only endpoints must be disabled on all production OPC UA servers.

Need OPC UA BMS integration for your building project?

We integrate BACnet, Modbus, KNX, and M-Bus subsystems into a unified OPC UA layer — connecting energy meters, HVAC controllers, and SCADA to cloud analytics and energy management platforms.

Request a quote →
Loading...
Back to top