v3 B1-WP2: TagConfigIntent sheds FullName identity; RawPaths tests; nodeId key normalization
This commit is contained in:
@@ -3,21 +3,24 @@ using System.Text.Json.Nodes;
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
|
||||
|
||||
/// <summary>Typed working model for an OPC UA Client (gateway) equipment tag's TagConfig JSON. The tag
|
||||
/// is bound to the upstream OPC UA server node by its full reference (<c>FullName</c> — the persisted
|
||||
/// is bound to the upstream OPC UA server node by its full reference (<c>nodeId</c> — the persisted
|
||||
/// stable <c>nsu=…;s=…</c> or plain <c>ns=2;s=…</c> NodeId the driver reads/writes/subscribes against).
|
||||
/// Preserves unrecognised JSON keys across a load→save.</summary>
|
||||
/// <remarks>
|
||||
/// The <c>FullName</c> key is intentionally PascalCase: the shared deploy-time parser
|
||||
/// (<c>Commons.Types.TagConfigIntent.Parse</c>, consumed by the composer, artifact decoder, draft
|
||||
/// gate, and node walker) reads it via a case-sensitive <c>TryGetProperty("FullName", …)</c>, so the editor MUST persist that exact
|
||||
/// casing. The driver-agnostic server-side HistoryRead intent keys (<c>isHistorized</c> /
|
||||
/// Under the v3 identity contract, <c>TagConfig</c> no longer carries identity — the upstream
|
||||
/// node reference is an ordinary driver-specific address field. The key is the camelCase
|
||||
/// <c>nodeId</c> (replacing the legacy PascalCase <c>FullName</c> identity convention). The
|
||||
/// driver-agnostic server-side HistoryRead intent keys (<c>isHistorized</c> /
|
||||
/// <c>historianTagname</c>) are NOT modelled here — they are owned by the TagModal-merge seam
|
||||
/// (<see cref="TagHistorizeConfig"/>) and survive a load→save of this model as preserved unknown keys.
|
||||
/// </remarks>
|
||||
public sealed class OpcUaClientTagConfigModel
|
||||
{
|
||||
/// <summary>The camelCase TagConfig JSON key holding the upstream node reference.</summary>
|
||||
internal const string NodeIdKey = "nodeId";
|
||||
|
||||
/// <summary>Upstream OPC UA node reference the tag binds to (the driver-side full reference). Required.</summary>
|
||||
public string FullName { get; set; } = "";
|
||||
public string NodeId { get; set; } = "";
|
||||
|
||||
private JsonObject _bag = new();
|
||||
|
||||
@@ -30,24 +33,24 @@ public sealed class OpcUaClientTagConfigModel
|
||||
var o = TagConfigJson.ParseOrNew(json);
|
||||
return new OpcUaClientTagConfigModel
|
||||
{
|
||||
FullName = TagConfigJson.GetString(o, "FullName") ?? "",
|
||||
NodeId = TagConfigJson.GetString(o, NodeIdKey) ?? "",
|
||||
_bag = o,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Serialises this model back to a TagConfig JSON string over the preserved key bag.
|
||||
/// <c>FullName</c> is written PascalCase (the composer/walker contract key); any history keys merged
|
||||
/// by the TagModal (<c>isHistorized</c> / <c>historianTagname</c>) are carried through untouched as
|
||||
/// preserved unknown keys.</summary>
|
||||
/// <c>nodeId</c> is written camelCase (the v3 address key); any history keys merged by the TagModal
|
||||
/// (<c>isHistorized</c> / <c>historianTagname</c>) are carried through untouched as preserved unknown
|
||||
/// keys.</summary>
|
||||
/// <returns>The serialised TagConfig JSON string.</returns>
|
||||
public string ToJson()
|
||||
{
|
||||
TagConfigJson.Set(_bag, "FullName", FullName.Trim());
|
||||
TagConfigJson.Set(_bag, NodeIdKey, NodeId.Trim());
|
||||
return TagConfigJson.Serialize(_bag);
|
||||
}
|
||||
|
||||
/// <summary>Validation hook; returns an error message or null when the model is valid.</summary>
|
||||
/// <returns>An error message describing the validation failure, or <c>null</c> when valid.</returns>
|
||||
public string? Validate()
|
||||
=> string.IsNullOrWhiteSpace(FullName) ? "An upstream node reference (FullName) is required." : null;
|
||||
=> string.IsNullOrWhiteSpace(NodeId) ? "An upstream node reference (nodeId) is required." : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user