Formula Expressions
Mehrere OctoMesh-Funktionen erlauben es Ihnen, eine Formel einzugeben – einen kleinen numerischen Ausdruck, der
einen oder mehrere Eingabewerte referenziert und einen einzelnen Wert erzeugt. Alle nutzen dieselbe Formel-Engine
(mXparser, gekapselt als IFormulaEngine), sodass die nachfolgende Syntax überall identisch ist,
wo eine Formel akzeptiert wird.
Wo Formeln verwendet werden
| Funktion | Eingabevariable(n) | Hinweise |
|---|---|---|
DataPointMapping MappingExpression | value – der abgefragte Quellwert | Wird vom Adapter ausgewertet, wenn ein Steuerwert auf ein Zielattribut abgebildet wird. Vor dem Speichern mit der validate-expression-API validieren. |
| Berechnete Archivspalten | jede Quellspalte, gebunden über ihren Spaltennamen (z. B. activepower, apparentpower) | Wird zum Zeitpunkt des Archiv-Ingests (sowie während Backfill / Rollup) für jede Zeile ausgewertet. Ein null / NaN-Ergebnis speichert SQL NULL. Der ResultType wird mit der Spalte gespeichert und steuert das Rückcasting (siehe unten). |
Runtime-Query-@-Ausdrücke | (keine – Konstanten + Funktionen) | Ein mit @ präfigierter Query-Suchbegriff wird als Formel ausgewertet (z. B. eine Zeitgrenze @startOfDay(0)). |
Die Engine rechnet mit double. Eingaben und Ergebnisse sind Zahlen; Booleans sind 0 / 1 und
Datums-/Zeitwerte sind .NET-Ticks. In Formeln gibt es keine Zeichenketten-Verarbeitung.
Variablen
Eine Formel referenziert ihre Eingaben über den Namen. Für ein DataPointMapping ist die einzige Eingabe value;
andere Funktionen binden ihre eigenen Namen (z. B. bindet eine berechnete Archivspalte jede Quellspalte über
ihren Spaltennamen). Ein Name, der von der Funktion nicht bereitgestellt wird, ist ein Syntaxfehler.
Operatoren
| Kategorie | Operatoren |
|---|---|
| Arithmetik | + - * / ^ (Potenz) % (Modulo) |
| Vergleich | < <= > >= == != |
| Gruppierung | ( … ) |
Vergleichsergebnisse werden mit den logischen Operatoren && (und), || (oder) und ! (nicht) kombiniert.
Bedingungen
Beide Formen werden akzeptiert und sind gleichwertig:
value > 0 ? value : 0
if(value > 0, value, 0)
Der ternäre Operator im C-Stil cond ? a : b wird vor der Auswertung zu mXparsers if(cond, a, b)
normalisiert. Verschachtelung wird unterstützt; verwenden Sie zur Klarheit Klammern:
value > 100 ? 100 : (value < 0 ? 0 : value)
Eingebaute Funktionen (mXparser)
Die Engine ist der vollständige mXparser-Parser (v6.x) – nichts ist deaktiviert –
sodass die gesamte mXparser-Math Collection verfügbar ist, nicht nur die Handvoll, die die meisten Formeln verwenden.
Da jede Eingabe und das Ergebnis double sind (siehe den Hinweis zur numerischen Engine oben), ist der numerische
Teil dieser Collection das, was praktisch nützlich ist; die Helfer für Zeichenketten / Einheiten / Wahrscheinlichkeitsverteilungen
existieren, haben hier aber keine Zeichenketten- oder Einheiten-Eingaben, auf denen sie arbeiten können.
Die am häufigsten verwendeten Funktionen:
| Funktion | Bedeutung |
|---|---|
abs(x) | Absolutwert |
sgn(x) | Vorzeichen (-1 / 0 / +1) |
min(a, b, …) / max(a, b, …) | Minimum / Maximum (beliebig viele Argumente) |
round(x, n) | auf n Nachkommastellen runden |
floor(x) / ceil(x) | abrunden / aufrunden |
sqrt(x) | Quadratwurzel |
exp(x) | e^x |
ln(x) / log2(x) / log10(x) | natürlicher / Basis-2- / Basis-10-Logarithmus |
log(a, b) | Logarithmus mit expliziter Basis (Argumentreihenfolge siehe Referenz) |
mod(a, b) | Modulo (wie der %-Operator) |
if(cond, a, b) | Bedingung |
iff(c1, v1, c2, v2, …) | mehrzweigige Bedingung – die erste wahre Bedingung gewinnt |
Weitere Kategorien der Collection, die auf numerischen Eingaben arbeiten:
| Kategorie | Beispiele |
|---|---|
| Trigonometrie (Bogenmaß) | sin(x) cos(x) tan(x) cot(x) sec(x) csc(x) |
| Invers / hyperbolisch | asin(x) acos(x) atan(x), sinh(x) cosh(x) tanh(x) |
| Winkelumrechnung | rad(deg) (Grad→Bogenmaß), deg(rad) (Bogenmaß→Grad) |
| Runden / Teile | floor(x) ceil(x) round(x,n), frac(x) (Nachkommaanteil) |
| Kombinatorik / Zahlentheorie | gcd(a,b,…) lcm(a,b,…) C(n,k) (Binomialkoeffizient), n! (Fakultät) |
| Aggregation | min(…) max(…), gcd(…) lcm(…) |
Diese Tabelle ist eine kuratierte Teilmenge. Die maßgebliche, versionsgenaue Liste jeder Funktion, jedes Operators und jeder Konstante, die der Parser akzeptiert, ist die mXparser Math Collection. Alles, was dort aufgeführt ist und nur numerische Argumente entgegennimmt, funktioniert in einer OctoMesh-Formel.
Konstanten
mXparser liefert eine große Menge mathematischer und physikalischer Konstanten mit. Diejenigen, die Sie am wahrscheinlichsten verwenden:
| Konstante | Wert |
|---|---|
pi | π ≈ 3.14159 |
e | Eulersche Zahl ≈ 2.71828 |
[phi] | Goldener Schnitt ≈ 1.61803 |
[gam] | Euler–Mascheroni-Konstante ≈ 0.57722 |
true / false | 1 / 0 (praktisch mit den logischen Operatoren) |
(Physikalische Konstanten wie die Lichtgeschwindigkeit sind ebenfalls definiert – siehe Referenz. Wie bei den Funktionen sind hier nur ihre numerischen Werte relevant.)
OctoMesh-Erweiterungen
Diese drei werden von OctoMesh zusätzlich zur Standard-Collection registriert (siehe OctoExpression /
NowFunction / StartOfDayFunction in Runtime.Engine.Formulas):
| Funktion / Konstante | Bedeutung |
|---|---|
now(addMinutes) | aktueller Zeitstempel als .NET-Ticks, versetzt um addMinutes Minuten (negativ = Vergangenheit) |
startOfDay(dayCount) | lokale Mitternacht als .NET-Ticks, verschoben um dayCount Tage (startOfDay(0) = heute, startOfDay(-1) = gestern) |
null | der Null-Sentinel – siehe unten |
Beide Datumsfunktionen geben Ticks zurück, sie sind also für einen DateTime-Ergebnistyp oder für
Vergleiche gegen andere Tick-Werte gedacht (z. B. eine Runtime-Query-Zeitgrenze @startOfDay(0)).
Null- und Fehlerbehandlung
- Eine fehlende / null Eingabe bindet an den
null-Sentinel. - Wenn eine Formel zu NaN (z. B.
0 / 0) oder zumnull-Sentinel auswertet, wird der Wert als kein Ergebnis behandelt – Funktionen bilden dies auf einen Fallback ab (DataPointMapping behält den rohen numerischen Wert; eine berechnete Archivspalte speichertNULL). - Ein Syntaxfehler (unausgeglichene Klammern, unbekannte Variable, fehlerhafter Ausdruck) wird zum Validierungszeitpunkt gemeldet, bevor die Formel jemals verwendet wird.
Beispiele
| Ausdruck | Bedeutung |
|---|---|
value / 100 | Prozent in Verhältnis skalieren |
value * 100 | Verhältnis in Prozent skalieren |
value - 2.5 | Kalibrierungs-Offset |
abs(value) | Betrag |
min(max(value, 0), 100) | auf 0…100 begrenzen |
value > 0 ? value : 0 | nur positiver Anteil |
value < 0 ? abs(value) : 0 | Betrag des negativen Anteils (z. B. Entladeleistung) |
Eine Formel validieren
Für DataPointMapping stellt der Communication Controller einen maßgeblichen Validierungs-Endpunkt bereit, der dieselbe Engine ausführt, die der Adapter zur Laufzeit verwendet, sodass eine Formel, die validiert, auch läuft:
POST {tenantId}/v1/communication/validate-expression
{ "expression": "value > 0 ? value : 0", "testValue": 42.0 }
Er gibt { valid, error, result, normalizedExpression } zurück – result ist der Wert für den
übergebenen testValue, und normalizedExpression zeigt das Umschreiben von ternär zu if.
Ergebnistypen
Funktionen, die ein Formelergebnis persistieren (insbesondere berechnete Archivspalten), speichern einen Ergebnistyp
neben dem Ausdruck. Die Engine wertet zu double aus und castet dann zurück:
| Ergebnistyp | Rückcasting |
|---|---|
Double | der rohe Wert |
Int | auf eine 32-Bit-Ganzzahl abgeschnitten |
Int64 | auf eine 64-Bit-Ganzzahl abgeschnitten |
Boolean | false, wenn der Wert 0 ist, andernfalls true |
DateTime | der Wert wird als .NET-Ticks interpretiert (passt natürlich zu now() / startOfDay()) |
Ein null-Sentinel- oder NaN-Ergebnis wird unabhängig vom gewählten Typ immer auf null abgebildet.
Die Engine selbst – der IFormulaEngine-Servicevertrag, die mXparser-Abhängigkeit, die DI-Registrierung
und die gemeinsamen Konventionen zu ternär / null / Rückcasting – ist im
Entwicklerhandbuch dokumentiert: Formula Engine.