Python · recipe
Read historical data in Python
Check the server claims historical access, then read a bounded time range. Ask for aggregates rather than raw values when you want a shift average: the server computes it far more cheaply than you can after streaming everything.
| Stack | asyncua (FreeOpcUa/opcua-asyncio) |
|---|---|
| Version | 2.0.1 |
The code
import asyncio
from datetime import datetime, timedelta, timezone
from asyncua import Client
async def main():
async with Client(url="opc.tcp://milo.digitalpetri.com:62541/milo") as client:
node = client.get_node("ns=2;s=Dynamic/RandomDouble")
end = datetime.now(timezone.utc)
start = end - timedelta(minutes=10)
values = await node.read_raw_history(start, end, numvalues=5)
for dv in values:
print(dv.SourceTimestamp, dv.Value.Value, dv.StatusCode)
asyncio.run(main())
What it prints
2026-09-08 03:35:00.001000+00:00 41.2 StatusCode(Good)
2026-09-08 03:36:00.002000+00:00 43.8 StatusCode(Good)
2026-09-08 03:37:00.001000+00:00 39.1 StatusCode(Good)
2026-09-08 03:38:00.003000+00:00 44.6 StatusCode(Good)
2026-09-08 03:39:00.001000+00:00 42.0 StatusCode(Good)
Notes
- Always bound the request with numvalues or a short window. An unbounded history read against a busy historian is a good way to be blamed for an outage.
- Read ServerProfileArray first. If the server does not claim a historical access facet, no amount of client code will help.
- For shift figures, ask for TimeAverage, DurationGood or PercentGood rather than pulling raw values. Server-side aggregation is dramatically cheaper.
- A gap in returned history is real information: it usually means the collector was down, and that matters for an availability calculation.
- CLI equivalent: `uahistoryread -u <url> -n "ns=2;s=Dynamic/RandomDouble" --starttime ...`.
What breaks first
The read fails because the server does not implement historical access
Check ServerProfileArray for a historical access facet. If it is absent, collect and store the data yourself via a subscription.
BadHistoryOperationUnsupportedCheck ServerProfileArray for a historical access facet. If it is absent, collect and store the data yourself via a subscription.
Other recipes in this stack
Concepts on this page
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.