Zum Hauptinhalt springen

Status eines Datenpunkts

Jeder gespeicherte Zeitreihenpunkt trägt neben Zeitstempel und Wert einen Status, das Feld flags (32-Bit-Ganzzahl). Sein Aufbau folgt dem StatusCode aus OPC UA (OPC 10000-4) – und zwar für alle Quellen, nicht nur für OPC UA: Ein über MQTT gelieferter, importierter oder in der Plattform verdichteter Wert wird mit denselben Bits beschrieben. Woher ein Wert stammt, steht nicht im Status, sondern an der Metrik (Herkunft MQTT, OPC_UA, IMPORT, …).

Der Wert 0 bedeutet Good, Rohwert und ist der Normalfall.

Bitbelegung​

BitsBedeutungWerte
30–31Severity00 Good, 01 Uncertain, 10 Bad
28–29reserviert (OPC UA)–
16–27SubCode, die genaue Ursachez. B. Bad_NoData = 0x809B0000
14–15SemanticsChanged / StructureChanged–
13Plattform, derzeit nicht belegt–
12Plattform: gelöscht (4096)gesetzt = Punkt ist ungültig gemacht
10–11InfoType01 = die Bits 0–9 sind belegt
8–9GrenzwertLow, High, Constant
7Overflow–
5–6reserviert (OPC UA)–
4MultiValuemehrere Werte am selben Zeitstempel
3ExtraData–
2Partialberechnet über ein Fenster mit Datenlücke
0–1Herkunft des Werts00 Rohwert, 01 berechnet, 10 interpoliert

Die Bits 12 und 13 sind im StatusCode reserviert und gehören der Plattform. Eine Datenquelle kann sie nicht setzen; das Bit 12 markiert einen über die Plattform gelöschten Punkt.

Was die Plattform heute setzt​

SituationStatus
Wert von einem OPC-UA-Serverder StatusCode, den der Server mitgeliefert hat – auch Uncertain und Bad
Wert über MQTT mit Feld statusdieser StatusCode
Wert über MQTT ohne status, Import, Formular0 (Good, Rohwert)
Punkt über einen Kommentar oder die Plattform gelöschtBit 12 gesetzt
Verdichteter Wert beim Lesen (Plot-Aggregation, AVG:1h u. Ä.)der Status des Zeitfensters, siehe unten

Die Bits 12 und 13 einer Quelle verwirft die Plattform beim Eingang.

Ein Bad-Wert wird ohne Zahl gespeichert (value ist leer, NULL), mit seinem Status – auch wenn der Server einen Ersatzwert mitliefert. Ein Bad-Wert ist nach OPC UA nicht verwendbar, und eine Ersatzzahl ginge sonst als Messwert in Plot, Aggregate und Zustandsüberwachung ein. Uncertain-Werte behalten ihre Zahl. Leer statt NaN, weil Mittelwert, Minimum und Maximum einen leeren Wert überspringen, während ein einziges NaN das Ergebnis eines ganzen Zeitfensters zu NaN macht. Im Plot erscheint ein solcher Punkt als Lücke; die Zustandsüberwachung und der Plattform-Adapter des hetida designers lassen ihn aus, und der „letzte Wert“ einer Kennzahl ist der letzte Punkt mit Zahl.

Status verdichteter Werte​

Fordert ein Leser die Werte verdichtet an (Plot-Aggregation, AVG:1h, MAX:15m …), berechnet die Plattform jedes Zeitfenster nach OPC UA Part 13 (OPC 10000-13):

  • Nur Good-Werte gehen in die Zahl ein. Uncertain-Werte werden wie Bad behandelt (TreatUncertainAsBad, Voreinstellung der Norm) und bleiben draußen – auch beim Einzelwert über einen Zeitraum (/aggregation, z. B. für Kennzahlen).
  • Der Status des Fensters ergibt sich aus der Zahl der Werte:
Fenster enthältStatus
nur Good-Werte1 (Good, berechnet)
Good- und andere WerteUncertain_DataSubNormal, berechnet
keinen Good-WertBad_NoData, ohne Wert
gar keinen Wertkeine Zeile
  • Bei LAST macht ein schlechter Wert das Fenster nur dann unsicher, wenn er nach dem gelieferten letzten Good-Wert liegt.
  • Partial (Bit 2) tragen MIN, MAX und LAST, wenn das Fenster vom Abfragezeitraum angeschnitten wird oder noch nicht abgeschlossen ist. AVG setzt Partial nach der Norm nie, SUM und MEDIAN (kein Gegenstück in der Norm) verhalten sich wie AVG.

Status verdichteter Werte aus OPC UA und MQTT​

Ist an einem OPC-UA-Knoten oder an einer MQTT-Metrik eine Verdichtung eingestellt (z. B. Mittelwert je 15 Minuten), trägt jeder verdichtete Wert ebenfalls einen Status nach OPC UA Part 13. Auch hier gehen nur Good-Werte in die Zahl ein:

VerdichtungStatus
Wert am Rasterpunktder Status des Werts, der zum Rasterbeginn gilt – Rohwert, wenn er genau dort liegt, sonst interpoliert; ist er Bad, ein Punkt ohne Wert
Mittelwertzeitgewichtet: nur Good-Zeit → Good, berechnet; mit schlechten Zeiten → Uncertain_DataSubNormal (die schlechte Zeit zählt nicht mit); keine Good-Zeit → Bad_NoData ohne Wert
Minimum, Maximumnur Good-Werte → Good, berechnet; daneben andere → Uncertain_DataSubNormal; keiner Good → Bad_NoData ohne Wert; ein Fenster ohne eigenen Wert entfällt
Bei Änderungder Status des Rohwerts; ein Statuswechsel erzeugt einen Punkt wie ein Wertsprung

Verdichtet der OPC-UA-Server selbst, übernimmt die Plattform dessen Status; ein Fenster, für das der Server Bad meldet, ergibt keinen Punkt – der Server unterscheidet dort nicht zwischen „keine Daten“ und „nur schlechte Daten“.

Geändert mit HET-2184

Bis HET-2184 stand „gelöscht“ im Bit 2 (Wert 4). Das Bit heißt im StatusCode Partial; die Plattform hat die gespeicherten Punkte beim Update auf Bit 12 umgestellt. Ein Wert 4 bedeutet seitdem „berechnet über ein lückenhaftes Fenster“, nicht mehr „gelöscht“.

Status auslesen​

Bei Severity Bad ist das oberste Bit gesetzt, die Zahl ist dann negativ. Die Severity liest man deshalb über eine Verschiebung, nicht über eine Maske mit 0xC0000000 – die passt in SQL nicht in einen integer.

SELECT ts_timestamp,
value,
CASE (flags >> 30) & 3
WHEN 0 THEN 'Good'
WHEN 1 THEN 'Uncertain'
WHEN 2 THEN 'Bad'
END AS severity,
(flags & 3) = 1 AS berechnet,
(flags & 4) <> 0 AS partial
FROM timeseries
WHERE metric_id = '…'
AND (flags & 4096) = 0; -- gelöschte Punkte ausblenden
def status(flags: int) -> dict:
flags &= 0xFFFFFFFF # negative int32 als vorzeichenlose 32 Bit lesen
return {
"severity": ("Good", "Uncertain", "Bad", "reserviert")[flags >> 30],
"sub_code": (flags >> 16) & 0xFFF,
"herkunft": ("Rohwert", "berechnet", "interpoliert", "reserviert")[flags & 3],
"partial": bool(flags & 4),
"geloescht": bool(flags & 4096),
}