docs(v3-batch3): UNS reference-only Equipment + {{equip}}/RefName resolution
Uns.md Tags section rewritten to the reference-only model (UnsTagReference list,
cluster-scoped picker, effective-name uniqueness, {{equip}}/RefName); CLAUDE.md
gains a v3 Batch 3 paragraph. ScriptEditor.md was updated by WP4.
Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
This commit is contained in:
@@ -217,6 +217,8 @@ The AdminUI's global **UNS** page (`/uns`) is the single surface for managing th
|
|||||||
|
|
||||||
**v3 (Batch 2): device I/O is authored in the `/raw` project tree** (`GlobalRaw.razor` → `RawTree.razor`, `IRawTreeService`) — a cluster-rooted `Folder → Driver → Device → TagGroup → Tag` hierarchy with per-node context menus (the reusable `ContextMenu`), lazy loading, driver/device config modals (endpoint moved to `Device.DeviceConfig`; Test-connect probes the `DriverDeviceConfigMerger`-merged config), manual-entry + CSV import/export (RFC-4180, staged review grid, all-or-nothing), and browse-commit of discovered leaves into raw tags. The routed `/clusters/{id}/drivers` flow (`DriverTypePicker`, `DriverEditRouter`, the 8 `*DriverPage` shells, the Drivers list) is **retired** — its form bodies live on inside the `/raw` modals. The `DriverType` dispatch maps are keyed off the `DriverTypeNames` constants (fixing the `TwinCat`/`Focas` drift). A `Calculation` pseudo-driver (`DriverTypeNames.Calculation`, `IDependencyConsumer`, deploy-time `scriptId`-existence + Tarjan cycle gates) computes signal-level tags from other tags' RawPaths. See `docs/Raw.md`.
|
**v3 (Batch 2): device I/O is authored in the `/raw` project tree** (`GlobalRaw.razor` → `RawTree.razor`, `IRawTreeService`) — a cluster-rooted `Folder → Driver → Device → TagGroup → Tag` hierarchy with per-node context menus (the reusable `ContextMenu`), lazy loading, driver/device config modals (endpoint moved to `Device.DeviceConfig`; Test-connect probes the `DriverDeviceConfigMerger`-merged config), manual-entry + CSV import/export (RFC-4180, staged review grid, all-or-nothing), and browse-commit of discovered leaves into raw tags. The routed `/clusters/{id}/drivers` flow (`DriverTypePicker`, `DriverEditRouter`, the 8 `*DriverPage` shells, the Drivers list) is **retired** — its form bodies live on inside the `/raw` modals. The `DriverType` dispatch maps are keyed off the `DriverTypeNames` constants (fixing the `TwinCat`/`Focas` drift). A `Calculation` pseudo-driver (`DriverTypeNames.Calculation`, `IDependencyConsumer`, deploy-time `scriptId`-existence + Tarjan cycle gates) computes signal-level tags from other tags' RawPaths. See `docs/Raw.md`.
|
||||||
|
|
||||||
|
**v3 (Batch 3): UNS Equipment is reference-only.** The equipment **Tags** tab no longer authors or binds tags — it holds `UnsTagReference` rows pointing at raw tags authored in `/raw`. "+ Add reference" opens the `RawTree` in picker mode, **cluster-scoped** (structurally + server-enforced `tag.cluster == equipment.cluster`); rows show effective name / RawPath / inherited DataType+AccessLevel / display-name override. **Effective-name uniqueness** (references + VirtualTags + ScriptedAlarms share the `{EquipmentId}/{EffectiveName}` NodeId space) is enforced at authoring (`IEffectiveNameGuard`) and at the deploy gate (`DraftValidator.UnsEffectiveNameCollision` — catches rename-induced collisions). Scripts use **`ctx.GetTag("{{equip}}/<RefName>")`** — resolved per-equipment through `UnsTagReference` effective names to the backing RawPath at both compose seams (`AddressSpaceComposer` + `DeploymentArtifact`, via the shared `EquipmentReferenceMap`, byte-parity); an unresolved `<RefName>` is a deploy error (`EquipReferenceUnresolved`) AND a live Monaco diagnostic (`OTSCRIPT_EQUIPREF`) — editor accepts ⇔ publish accepts. `EquipmentScriptPaths.DeriveEquipmentBase` is deleted (the dot-joint `{{equip}}.X` became the slash-joint `{{equip}}/<RefName>`). Raw rename warns when a beneath-it tag is historized-without-override / UNS-referenced / named by a script literal (`RawTreeService` substring scan). `ImportEquipmentModal` dropped the `DriverInstanceId` column. See `docs/Uns.md` + `docs/ScriptEditor.md`.
|
||||||
|
|
||||||
The `/uns` **TagModal** uses **driver-typed tag-config editors**: it dispatches by the bound driver's `DriverType` to a per-driver editor (Modbus/S7/AbCip/AbLegacy/TwinCAT/Focas/OpcUaClient) via `TagConfigEditorMap`, with client-side validation via `TagConfigValidator`; unmapped drivers (only Galaxy) fall back to the generic raw-`TagConfig`-JSON textarea. Each editor is a thin razor shell over a pure `<Driver>TagConfigModel` (`FromJson`/`ToJson`/`Validate`, preserves unknown keys). To add a driver's editor, copy the Modbus template under `Components/Shared/Uns/TagEditors/` + `Uns/TagEditors/`, reusing the driver's enums + camelCase JSON property names, and register it in `TagConfigEditorMap` + `TagConfigValidator`. See `docs/plans/2026-06-09-driver-typed-tag-editors-design.md`.
|
The `/uns` **TagModal** uses **driver-typed tag-config editors**: it dispatches by the bound driver's `DriverType` to a per-driver editor (Modbus/S7/AbCip/AbLegacy/TwinCAT/Focas/OpcUaClient) via `TagConfigEditorMap`, with client-side validation via `TagConfigValidator`; unmapped drivers (only Galaxy) fall back to the generic raw-`TagConfig`-JSON textarea. Each editor is a thin razor shell over a pure `<Driver>TagConfigModel` (`FromJson`/`ToJson`/`Validate`, preserves unknown keys). To add a driver's editor, copy the Modbus template under `Components/Shared/Uns/TagEditors/` + `Uns/TagEditors/`, reusing the driver's enums + camelCase JSON property names, and register it in `TagConfigEditorMap` + `TagConfigValidator`. See `docs/plans/2026-06-09-driver-typed-tag-editors-design.md`.
|
||||||
|
|
||||||
## Scripting / Script Editor
|
## Scripting / Script Editor
|
||||||
|
|||||||
+39
-12
@@ -74,26 +74,53 @@ changed by editing the area's cluster in the Area modal, which moves the
|
|||||||
whole branch. There is no separate "served-by" concept and no migration —
|
whole branch. There is no separate "served-by" concept and no migration —
|
||||||
it is simply `UnsArea.ClusterId`.
|
it is simply `UnsArea.ClusterId`.
|
||||||
|
|
||||||
### Tags
|
### Tags — reference-only (v3)
|
||||||
|
|
||||||
Tags created on the equipment page are **equipment-bound** and require a driver
|
> **v3 (Batch 3):** UNS equipment no longer authors or binds tags. Device I/O is
|
||||||
instance. The driver list on the Tags tab is scoped to the equipment's cluster
|
> authored once in the **Raw project tree** (`/raw` — see [`Raw.md`](Raw.md)); an
|
||||||
and to drivers on an **Equipment-kind** namespace, so a driver-less equipment
|
> equipment's **Tags** tab holds **references** to those raw tags. The old
|
||||||
shows no eligible drivers until you bind one (edit the equipment on the Details
|
> driver-bound Tag modal on this tab is retired.
|
||||||
tab and pick a driver).
|
|
||||||
|
|
||||||
**Galaxy / AVEVA System Platform points are ordinary equipment tags** bound to
|
The **Tags** tab is a list of `UnsTagReference` rows. Each row shows the
|
||||||
a `GalaxyMxGateway` driver instance. Author them on the Tags tab using the
|
**effective name**, the backing tag's **RawPath**, its inherited **DataType** and
|
||||||
standard Tag modal; the Galaxy address picker browses the live Galaxy hierarchy
|
**AccessLevel** (read-only — they come from the raw tag), and an editable
|
||||||
so you can select the attribute and set `TagConfig.FullName`. There is no
|
**display-name override**. The effective name is the override else the raw tag's
|
||||||
separate alias concept or `SystemPlatform`-kind namespace.
|
`Name`.
|
||||||
|
|
||||||
|
**"+ Add reference"** opens a raw-tree picker (the `/raw` tree in picker mode)
|
||||||
|
**scoped to the equipment's cluster** — cross-cluster tags are structurally
|
||||||
|
unreachable, and the service also enforces `tag.cluster == equipment.cluster` on
|
||||||
|
commit. Tick individual tag leaves, or use a device / tag-group's *"Select all
|
||||||
|
tags below"* menu to pull many at once.
|
||||||
|
|
||||||
|
**Effective-name uniqueness:** within an equipment the effective name must be
|
||||||
|
unique across references, VirtualTags, and ScriptedAlarms (they share the
|
||||||
|
equipment's UNS NodeId space, `{EquipmentId}/{EffectiveName}`). This is enforced
|
||||||
|
both at authoring (a readable rejection naming the colliding source) and at the
|
||||||
|
deploy gate (`DraftValidator`, `UnsEffectiveNameCollision`) — the deploy gate is
|
||||||
|
what catches **rename-induced** collisions a raw rename produced after the
|
||||||
|
reference was authored, naming both colliding sources and the equipment.
|
||||||
|
|
||||||
|
Removing a raw tag in `/raw` is blocked while a `UnsTagReference` points at it
|
||||||
|
(the error names the referencing equipment); renaming a raw tag or any ancestor
|
||||||
|
warns when a beneath-it tag is historized (no `historianTagname` override),
|
||||||
|
UNS-referenced, or named by a script literal — see [`Raw.md`](Raw.md).
|
||||||
|
|
||||||
|
**Galaxy / AVEVA System Platform points** are now ordinary raw tags on a
|
||||||
|
`GalaxyMxGateway` driver in `/raw`, referenced into equipment like any other raw
|
||||||
|
tag. There is no separate alias concept or `SystemPlatform`-kind namespace.
|
||||||
|
|
||||||
### Virtual tags
|
### Virtual tags
|
||||||
|
|
||||||
A virtual tag is bound to an equipment and driven by a **script** (no driver).
|
A virtual tag is bound to an equipment and driven by a **script** (no driver).
|
||||||
Add and edit virtual tags on the equipment page's **Virtual Tags** tab; the
|
Add and edit virtual tags on the equipment page's **Virtual Tags** tab; the
|
||||||
data type is chosen from the standard OPC UA type list and the Monaco script
|
data type is chosen from the standard OPC UA type list and the Monaco script
|
||||||
editor is available inline.
|
editor is available inline. Scripts may read the equipment's references
|
||||||
|
relative-to-equipment with **`ctx.GetTag("{{equip}}/<RefName>")`** — the token
|
||||||
|
resolves through the equipment's `UnsTagReference` rows (by effective name) to
|
||||||
|
the backing raw tag's RawPath at deploy; an unresolved `<RefName>` is a deploy
|
||||||
|
error and a live Monaco diagnostic (editor accepts ⇔ publish accepts). See
|
||||||
|
[`ScriptEditor.md`](ScriptEditor.md).
|
||||||
|
|
||||||
### Galaxy tags
|
### Galaxy tags
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user