Python · recipe

Subscribe to data changes in Python

Create a subscription with the publishing interval your consumer actually needs, then add monitored items with their own sampling interval, queue size and deadband. The handler is called on every notification, so keep it cheap and never block in it.

Stackasyncua (FreeOpcUa/opcua-asyncio)
Version2.0.1

The code

import asyncio
from asyncua import Client, ua

class Handler:
    def datachange_notification(self, node, val, data):
        dv = data.monitored_item.Value
        print(f"{node} = {val}  status={dv.StatusCode}  src={dv.SourceTimestamp}")

    def status_change_notification(self, status):
        print("subscription status:", status)

async def main():
    async with Client(url="opc.tcp://opcua.umati.app:4840") as client:
        handler = Handler()
        # publishing interval = what the consumer needs, not the fastest possible
        sub = await client.create_subscription(1000, handler)

        node = client.get_node("i=2258")
        mfilter = ua.DataChangeFilter(
            Trigger=ua.DataChangeTrigger.StatusValue,
            DeadbandType=ua.DeadbandType.Absolute.value,
            DeadbandValue=0.5,
        )
        await sub.subscribe_data_change(node, queuesize=10, monitorfilter=mfilter)

        await asyncio.sleep(5)
        await sub.delete()

asyncio.run(main())

What it prints

i=2258 = 2026-09-08 03:45:00.102000  status=StatusCode(Good)  src=2026-09-08 03:45:00.102000
i=2258 = 2026-09-08 03:45:01.104000  status=StatusCode(Good)  src=2026-09-08 03:45:01.104000
i=2258 = 2026-09-08 03:45:02.101000  status=StatusCode(Good)  src=2026-09-08 03:45:02.101000

Notes

  • The 1000 in create_subscription is the publishing interval in milliseconds: how often the server delivers. The sampling interval, set per item, is how often it looks. Confusing the two is the most common subscription mistake in OPC UA.
  • Percent deadband needs EURange on the node. Without it the deadband is silently ignored, so use Absolute unless you have checked.
  • Size queuesize from the publishing-to-sampling ratio. If it overflows, the overflow bit is set and the status still reads Good: the loss is silent.
  • Keep the handler non-blocking. It runs on the client's loop; heavy work there stalls the subscription.
  • Add a heartbeat if you need to distinguish 'value unchanged' from 'connection dead'.

What breaks first

Samples go missing while every status code still reads Good GoodOverload
The monitored item's queue overflowed between publishes. Increase queueSize, lengthen the sampling interval, or apply a deadband so fewer samples are generated.

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login