Skip to content
Start free evaluation

History

  • Write values to a historized variable to build up history.
  • Read the raw history of the last hour.
  • Limit how many values come back at once, then get or release the rest with a continuation point.
  • The apps package and the OPCUA_APPS variable from the lab setup.
  • One terminal.
터미널 창
"$OPCUA_APPS/bin/pdcomm-opcua-headless"
{"action":"server_start"}
{"action":"connect"}

Simulator.Double is recorded every time you write it. Write three values:

{"action":"write","node":"ns=2;s=Simulator.Double","type":"Double","value":1.5}
{"action":"write","node":"ns=2;s=Simulator.Double","type":"Double","value":2.5}
{"action":"write","node":"ns=2;s=Simulator.Double","type":"Double","value":3.5}

Each reply is {"ok":true,"result":{"good":true,...}}.

Without a period, the action reads from one hour ago to one minute from now:

{"action":"history_read","node":"ns=2;s=Simulator.Double"}
{"ok":true,"result":{"continuation":null,"good":true,"node":"ns=2;s=Simulator.Double","status":"Good (0x00000000)","values":[{"good":true,"source_time":1791997613205,"status":"Good (0x00000000)","type":"Double","value":0.0},{"good":true,"source_time":1791997613335,"status":"Good (0x00000000)","type":"Double","value":1.5},{"good":true,"source_time":1791997613339,"status":"Good (0x00000000)","type":"Double","value":2.5},{"good":true,"source_time":1791997613342,"status":"Good (0x00000000)","type":"Double","value":3.5}],"window":{"end":1791997673344,"start":1791994013344}}}

The first value, 0.0, is the initial value recorded when the server started. window is the period actually requested, in Unix milliseconds. To read another period, pass start and end in Unix milliseconds.

Limit each response to two values with max:

{"action":"history_read","node":"ns=2;s=Simulator.Double","max":2}
{"ok":true,"result":{"continuation":"25b15bec55060e062202f744cc176951d2dd625ee5c16f89d693cafbc31b8cd8","good":true,"node":"ns=2;s=Simulator.Double","status":"Good (0x00000000)","values":[{"good":true,"source_time":1791997613205,"status":"Good (0x00000000)","type":"Double","value":0.0},{"good":true,"source_time":1791997613335,"status":"Good (0x00000000)","type":"Double","value":1.5}],"window":{"end":1791997673348,"start":1791994013348}}}

More values remain, so continuation holds a continuation point. Pass it back to get the rest, replacing the value below with yours. The simulator reuses the first request’s period and max, so the continuation point is all you need.

{"action":"history_read","node":"ns=2;s=Simulator.Double","continuation":"25b15bec55060e062202f744cc176951d2dd625ee5c16f89d693cafbc31b8cd8"}
{"ok":true,"result":{"continuation":null,"good":true,"node":"ns=2;s=Simulator.Double","status":"Good (0x00000000)","values":[{"good":true,"source_time":1791997613339,"status":"Good (0x00000000)","type":"Double","value":2.5},{"good":true,"source_time":1791997613342,"status":"Good (0x00000000)","type":"Double","value":3.5}],"window":{"end":1791997673348,"start":1791994013348}}}

A null continuation means you have all the values.

If you don’t need the remaining values, release the continuation point to free the server’s resources. Get a new one:

{"action":"history_read","node":"ns=2;s=Simulator.Double","max":2}

Pass it with "release":true:

{"action":"history_read","node":"ns=2;s=Simulator.Double","continuation":"1ea43b51cfb7c23dc05a68b65c79eb93c4cdc05dea99375578f729ffcd7c4a4c","release":true}
{"ok":true,"result":{"continuation":null,"good":true,"node":"ns=2;s=Simulator.Double","status":"Good (0x00000000)","values":[],"window":{"end":1791997673356,"start":1791994013356}}}

A released continuation point can’t be used again:

{"action":"history_read","node":"ns=2;s=Simulator.Double","continuation":"1ea43b51cfb7c23dc05a68b65c79eb93c4cdc05dea99375578f729ffcd7c4a4c"}
{"ok":true,"result":{"continuation":null,"good":false,"node":"ns=2;s=Simulator.Double","status":"BadContinuationPointInvalid (0x804A0000)","values":[],"window":{"end":1791997673356,"start":1791994013356}}}

6. Empty periods and nodes without history

Section titled “6. Empty periods and nodes without history”

A period with no values, such as the first second of January 1, 1970, returns GoodNoData:

{"action":"history_read","node":"ns=2;s=Simulator.Double","start":0,"end":1000}
{"ok":true,"result":{"continuation":null,"good":true,"node":"ns=2;s=Simulator.Double","status":"GoodNoData (0x00A50000)","values":[],"window":{"end":1000,"start":0}}}

Simulator.Int32 exists, but its history isn’t stored. Reading its history returns BadHistoryOperationUnsupported:

{"action":"history_read","node":"ns=2;s=Simulator.Int32"}
{"ok":true,"result":{"continuation":null,"good":false,"node":"ns=2;s=Simulator.Int32","status":"BadHistoryOperationUnsupported (0x80720000)","values":[],"window":{"end":1792000524047,"start":1791996864047}}}

Reading a node that doesn’t exist, such as Simulator.Missing, returns BadNodeIdUnknown:

{"action":"history_read","node":"ns=2;s=Simulator.Missing"}
{"ok":true,"result":{"continuation":null,"good":false,"node":"ns=2;s=Simulator.Missing","status":"BadNodeIdUnknown (0x80340000)","values":[],"window":{"end":1792000524052,"start":1791996864052}}}
{"action":"shutdown"}
  • Simulator.Counter is historized too. Right after the server starts, two values are recorded in the same millisecond, so its first value can show the status Good (0x00000408) (HistorianExtraData); Historical access explains why.
  • When the service ran but the node’s result is Bad, the reply has ok true and good false.
  • In the GUI, Read raw history (last hour) on the History tab sends the same request.