feat(triggers): add Expression to the script & alarm trigger codecs
This commit is contained in:
@@ -93,6 +93,10 @@ internal static class AlarmTriggerConfigCodec
|
|||||||
model.HiMessage = TryReadString(root, "hiMessage");
|
model.HiMessage = TryReadString(root, "hiMessage");
|
||||||
model.HiHiMessage = TryReadString(root, "hiHiMessage");
|
model.HiHiMessage = TryReadString(root, "hiHiMessage");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AlarmTriggerType.Expression:
|
||||||
|
model.Expression = TryReadString(root, "expression");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (JsonException)
|
catch (JsonException)
|
||||||
@@ -105,8 +109,10 @@ internal static class AlarmTriggerConfigCodec
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Serializes the model to the JSON shape AlarmActor.ParseEvalConfig
|
/// Serializes the model to the JSON shape AlarmActor.ParseEvalConfig
|
||||||
/// expects. Always writes <c>attributeName</c> (canonical key) and only
|
/// expects. Writes <c>attributeName</c> (canonical key) for the
|
||||||
/// the keys relevant to the current trigger type.
|
/// attribute-bound trigger types and only the keys relevant to the
|
||||||
|
/// current trigger type. <c>Expression</c> is not bound to a single
|
||||||
|
/// attribute, so <c>attributeName</c> is omitted for it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string Serialize(AlarmTriggerModel model, AlarmTriggerType type)
|
internal static string Serialize(AlarmTriggerModel model, AlarmTriggerType type)
|
||||||
{
|
{
|
||||||
@@ -114,6 +120,7 @@ internal static class AlarmTriggerConfigCodec
|
|||||||
using (var w = new Utf8JsonWriter(stream))
|
using (var w = new Utf8JsonWriter(stream))
|
||||||
{
|
{
|
||||||
w.WriteStartObject();
|
w.WriteStartObject();
|
||||||
|
if (type != AlarmTriggerType.Expression)
|
||||||
w.WriteString("attributeName", model.AttributeName ?? "");
|
w.WriteString("attributeName", model.AttributeName ?? "");
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
@@ -155,6 +162,10 @@ internal static class AlarmTriggerConfigCodec
|
|||||||
if (!string.IsNullOrEmpty(model.HiMessage)) w.WriteString("hiMessage", model.HiMessage);
|
if (!string.IsNullOrEmpty(model.HiMessage)) w.WriteString("hiMessage", model.HiMessage);
|
||||||
if (!string.IsNullOrEmpty(model.HiHiMessage)) w.WriteString("hiHiMessage", model.HiHiMessage);
|
if (!string.IsNullOrEmpty(model.HiHiMessage)) w.WriteString("hiHiMessage", model.HiHiMessage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AlarmTriggerType.Expression:
|
||||||
|
w.WriteString("expression", model.Expression ?? "");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteEndObject();
|
w.WriteEndObject();
|
||||||
@@ -241,4 +252,7 @@ internal sealed class AlarmTriggerModel
|
|||||||
public string? LoMessage { get; set; }
|
public string? LoMessage { get; set; }
|
||||||
public string? HiMessage { get; set; }
|
public string? HiMessage { get; set; }
|
||||||
public string? HiHiMessage { get; set; }
|
public string? HiHiMessage { get; set; }
|
||||||
|
|
||||||
|
// Expression — boolean C# expression evaluated on attribute updates.
|
||||||
|
public string? Expression { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace ScadaLink.CentralUI.Components.Shared;
|
|||||||
/// trigger; <see cref="Unknown"/> is a stored trigger-type string the runtime
|
/// trigger; <see cref="Unknown"/> is a stored trigger-type string the runtime
|
||||||
/// does not recognize (preserved as-is by the editor).
|
/// does not recognize (preserved as-is by the editor).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal enum ScriptTriggerKind { None, Interval, ValueChange, Conditional, Call, Unknown }
|
internal enum ScriptTriggerKind { None, Interval, ValueChange, Conditional, Call, Expression, Unknown }
|
||||||
|
|
||||||
/// <summary>A script's trigger as the editor emits it: a type string + config JSON.</summary>
|
/// <summary>A script's trigger as the editor emits it: a type string + config JSON.</summary>
|
||||||
public sealed record ScriptTriggerValue(string? TriggerType, string? Config);
|
public sealed record ScriptTriggerValue(string? TriggerType, string? Config);
|
||||||
@@ -29,6 +29,9 @@ internal sealed class ScriptTriggerModel
|
|||||||
|
|
||||||
/// <summary>Comparison threshold (Conditional).</summary>
|
/// <summary>Comparison threshold (Conditional).</summary>
|
||||||
public double? Threshold { get; set; }
|
public double? Threshold { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Boolean C# expression (Expression).</summary>
|
||||||
|
public string? Expression { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -59,6 +62,7 @@ internal static class ScriptTriggerConfigCodec
|
|||||||
"valuechange" => ScriptTriggerKind.ValueChange,
|
"valuechange" => ScriptTriggerKind.ValueChange,
|
||||||
"conditional" => ScriptTriggerKind.Conditional,
|
"conditional" => ScriptTriggerKind.Conditional,
|
||||||
"call" => ScriptTriggerKind.Call,
|
"call" => ScriptTriggerKind.Call,
|
||||||
|
"expression" => ScriptTriggerKind.Expression,
|
||||||
_ => ScriptTriggerKind.Unknown
|
_ => ScriptTriggerKind.Unknown
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -70,6 +74,7 @@ internal static class ScriptTriggerConfigCodec
|
|||||||
ScriptTriggerKind.ValueChange => "ValueChange",
|
ScriptTriggerKind.ValueChange => "ValueChange",
|
||||||
ScriptTriggerKind.Conditional => "Conditional",
|
ScriptTriggerKind.Conditional => "Conditional",
|
||||||
ScriptTriggerKind.Call => "Call",
|
ScriptTriggerKind.Call => "Call",
|
||||||
|
ScriptTriggerKind.Expression => "Expression",
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,6 +109,10 @@ internal static class ScriptTriggerConfigCodec
|
|||||||
model.Operator = NormalizeOperator(op);
|
model.Operator = NormalizeOperator(op);
|
||||||
model.Threshold = TryReadDouble(root, "threshold") ?? TryReadDouble(root, "value");
|
model.Threshold = TryReadDouble(root, "threshold") ?? TryReadDouble(root, "value");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ScriptTriggerKind.Expression:
|
||||||
|
model.Expression = root.TryGetProperty("expression", out var e) ? e.GetString() : null;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (JsonException)
|
catch (JsonException)
|
||||||
@@ -144,6 +153,10 @@ internal static class ScriptTriggerConfigCodec
|
|||||||
w.WriteNumber("threshold", model.Threshold.Value);
|
w.WriteNumber("threshold", model.Threshold.Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ScriptTriggerKind.Expression:
|
||||||
|
w.WriteString("expression", model.Expression ?? "");
|
||||||
|
break;
|
||||||
|
|
||||||
// Call → empty object.
|
// Call → empty object.
|
||||||
}
|
}
|
||||||
w.WriteEndObject();
|
w.WriteEndObject();
|
||||||
|
|||||||
@@ -11,5 +11,11 @@ public enum AlarmTriggerType
|
|||||||
/// may carry its own priority; transitions between levels emit a fresh
|
/// may carry its own priority; transitions between levels emit a fresh
|
||||||
/// AlarmStateChanged with the corresponding <see cref="AlarmLevel"/>.
|
/// AlarmStateChanged with the corresponding <see cref="AlarmLevel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
HiLo
|
HiLo,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read-only boolean C# expression evaluated on attribute updates. The
|
||||||
|
/// trigger fires when the expression evaluates to <c>true</c>.
|
||||||
|
/// </summary>
|
||||||
|
Expression
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user