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.
What you need
Section titled “What you need”- The
appspackage and theOPCUA_APPSvariable from the lab setup. - One terminal.
1. Start the simulator and connect
Section titled “1. Start the simulator and connect”"$OPCUA_APPS/bin/pdcomm-opcua-headless"{"action":"server_start"}{"action":"connect"}2. Record values
Section titled “2. Record values”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,...}}.
3. Read raw history
Section titled “3. Read raw history”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.
4. Page through with a continuation point
Section titled “4. Page through with a continuation point”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.
5. Release a continuation point
Section titled “5. Release a continuation point”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}}}7. Clean up
Section titled “7. Clean up”{"action":"shutdown"}Simulator.Counteris historized too. Right after the server starts, two values are recorded in the same millisecond, so its first value can show the statusGood (0x00000408)(HistorianExtraData); Historical access explains why.- When the service ran but the node’s result is Bad, the reply has
oktrue andgoodfalse. - In the GUI, Read raw history (last hour) on the History tab sends the same request.