From bcba7a4bea5951d8badfa6d4cf38927e23e36863 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 19 Jun 2026 03:49:10 -0400 Subject: [PATCH] docs(opcua): note FB-7 surgical-shape reach (stable-FullName drivers only) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live-verify finding: the surgical DataType/array path only fires for drivers whose TagConfig carries a stable top-level FullName (Galaxy/OpcUaClient). For protocol drivers (Modbus/S7/...), ExtractTagFullName falls back to the raw TagConfig blob, so a shape edit also mutates FullName → safe full-rebuild fallback. Comment-only. --- .../ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs index cdcd9f74..2161b3db 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs @@ -401,6 +401,12 @@ public sealed class AddressSpaceApplier // differences still fall through to a rebuild — FullName/DriverInstanceId re-route the node to a different // driver point, Name re-derives the NodeId, and an alarm flip turns the node into a Part 9 condition. The // override-unequal default also covers any future field. + // REACH (live-verified FB-7): the shape path only fires for drivers whose TagConfig carries a stable + // top-level "FullName" (Galaxy = tag_name.AttributeName; OpcUaClient = the node id) — there a DataType/array + // edit leaves FullName untouched ⇒ surgical. For structured-TagConfig protocol drivers (Modbus/S7/AbCip/…) + // AddressSpaceComposer.ExtractTagFullName falls back to the RAW TagConfig blob as FullName, so a DataType/ + // array edit also mutates that blob ⇒ FullName differs ⇒ this returns false ⇒ full rebuild. That is the + // correct safe default (a protocol driver's subscription needs re-spawning for a new shape anyway). private static bool TagDeltaIsSurgicalEligible(AddressSpacePlan.EquipmentTagDelta d) => d.Previous.Alarm is null && d.Current.Alarm is null && (d.Previous with