A historian can store a valid timestamp and a numeric value even when that value should not be used in an average, alarm review, or production calculation. The missing context is often the OPC UA StatusCode carried with the value.
OPC UA data quality codes tell the client about the conditions under which a value was produced and whether it is usable. If the collector drops that information, downstream users may treat a stale, substituted, or otherwise questionable number as an ordinary process measurement.
StatusCode is more than a Good, Bad, or Uncertain label
Every OPC UA DataValue can contain a value, timestamps, and a StatusCode. The StatusCode is a 32-bit value. Its severity class is Good, Uncertain, or Bad, but the remaining bits can carry a more specific code and added information.
- Good means the operation succeeded and the associated result may be used.
- Uncertain means the result may not be suitable for every purpose. The subcode explains why.
- Bad means the value is not usable for the reason indicated by its subcode.
That severity check is the minimum. A historian integration should not collapse every non-Good condition into one generic flag if the detailed code matters to operations. Subcodes can distinguish different failure or uncertainty conditions. Information bits can also report conditions such as monitored-item queue overflow, limit state, or changed semantics.
The SemanticsChanged bit deserves attention. It can indicate that metadata such as engineering units changed and should be read again before the value is processed. A value of 100 is not comparable with yesterday’s 100 if the unit or scale changed between them.
A stored number is not automatically a usable measurement
Suppose a pressure transmitter normally reports around 5 bar. Communication to the device fails, but the historian path continues to write a numeric value without its quality status. A trend may look flat and stable. An hourly average may include that number. An investigator may conclude that the process was steady during the outage.
The problem is not that the historian failed to receive a row. It received an incomplete representation of the measurement. The source quality, value, and timestamp belong together.
Uncertain data requires a policy rather than a universal rejection rule. A value marked Uncertain may still help an operator understand direction or continuity, while being unsuitable for custody transfer, compliance reporting, or a production total. The subcode and business use determine the decision.
Bad values are clearer: OPC UA says they are not usable. A downstream calculation should not quietly treat a Bad value as a normal sample. Depending on the application, it may exclude the sample, return a quality-aware result, or stop the calculation and flag the interval.
Quality changes what historical calculations mean
Quality handling affects more than charts.
| Historical use | Risk when quality is ignored | Safer handling |
|---|---|---|
| Average temperature | Invalid or stale values bias the result | Filter or separately report non-Good samples |
| Production total | Questionable intervals produce unsupported totals | Define whether Uncertain data is allowed and record exclusions |
| Event investigation | A flat line can be mistaken for a stable process | Plot quality state with the value trend |
| Model training | Bad samples become misleading training data | Apply a documented quality filter before export |
| Availability reporting | Source failures disappear from the record | Retain quality transitions and outage intervals |
Avoid simply deleting every non-Good row at ingestion. Deletion removes evidence that the source or communication path had a problem. It is often better to preserve the received record and its quality, then apply use-specific rules in queries or curated datasets.
Preserve raw quality and define a usable-data rule
A durable historian design separates collection truth from analytical policy. If the collector provides the full StatusCode, retain its raw form when practical. A derived severity field can make routine filtering easier, but it should not replace the detailed code.
Document at least four decisions:
- Which source StatusCode field enters the collector?
- Which raw or derived quality field reaches historian storage?
- Which severities and subcodes each calculation accepts?
- How reports identify excluded, uncertain, or missing intervals?
Do not invent a value when the source has no usable measurement. Interpolation and carry-forward logic can support visualization or analysis, but mark the result as calculated or substituted. Otherwise the historian can no longer distinguish an observed value from an estimate.
Quality policy should also address late corrections. If a source sends a revised value or metadata change, decide whether historical calculations are recomputed and how the correction remains auditable.
Verify quality across the full path
Test one point before rolling the design across thousands of tags. Use an OPC UA client to record the source value, timestamp, full StatusCode, and readable status name. Compare that with the collector’s raw record and the destination row.
In a controlled test environment, create known Good, Uncertain, and Bad conditions where the server supports them. Confirm that the historian representation changes as expected. Also check a queue-overflow or semantic-change condition if those cases matter to the application.
Then run the downstream query. An average that excludes Bad data should produce a different result from an unfiltered average when the test window includes a Bad sample. A trend should make the quality transition visible. This proves that the status survived storage and that users actually handle it.
If the OPC UA connection works but records are missing from the historian, use this OPC UA troubleshooting guide to trace the collection and write path.
OPC UA quality mapping in TDengine
TDengine TSDB-Enterprise supports OPC UA ingestion through taosX. The current OPC UA CSV mapping reference includes an optional quality_col field. When configured, it names the TDengine column that stores OPC quality. Leaving it empty means the mapping does not add that quality column.
The documentation confirms the mapping field but does not state that every OPC UA StatusCode subcode and information bit is decoded into separate historian fields. Do not assume that level of preservation. Inspect the actual value written by the connector version in use, compare it with the source StatusCode, and document any transformation before building quality filters.
For industrial data stored in a time-series database, keeping value, timestamp, and quality together gives queries enough context to distinguish received data from usable data. The query or application still needs an explicit policy for Bad and Uncertain samples. Storage alone does not decide whether a measurement belongs in a particular calculation.


