From d8fa3a0dddbd67e05dd8e13b996995b81172d123 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 17 Apr 2026 12:54:35 -0400 Subject: [PATCH] =?UTF-8?q?Add=20OPC=2040010=20Machinery=20identity=20colu?= =?UTF-8?q?mns=20to=20the=20Equipment=20table=20(Manufacturer,=20Model,=20?= =?UTF-8?q?SerialNumber,=20HardwareRevision,=20SoftwareRevision,=20YearOfC?= =?UTF-8?q?onstruction,=20AssetLocation,=20ManufacturerUri,=20DeviceManual?= =?UTF-8?q?Uri=20=E2=80=94=20all=20nullable=20so=20equipment=20can=20be=20?= =?UTF-8?q?added=20before=20identity=20is=20fully=20captured)=20and=20surf?= =?UTF-8?q?ace=20them=20via=20a=20dedicated=20Identification=20panel=20in?= =?UTF-8?q?=20the=20Admin=20UI=20Equipment=20editor.=20These=20pair=20with?= =?UTF-8?q?=20the=20new=20`=5Fbase`=20equipment-class=20template=20seeded?= =?UTF-8?q?=20in=203yearplan/schemas/classes/=5Fbase.json=20that=20every?= =?UTF-8?q?=20other=20class=20extends=20=E2=80=94=20Manufacturer=20+=20Mod?= =?UTF-8?q?el=20are=20declared=20isRequired:=20true=20in=20the=20base,=20t?= =?UTF-8?q?he=20rest=20optional.=20Drivers=20that=20can=20read=20these=20d?= =?UTF-8?q?ynamically=20(FANUC=20cnc=5Fsysinfo()=20returning=20SoftwareRev?= =?UTF-8?q?ision,=20Beckhoff=20TwinCAT.SystemInfo,=20etc.)=20override=20th?= =?UTF-8?q?e=20static=20value=20at=20runtime;=20static=20value=20is=20the?= =?UTF-8?q?=20operator-set=20fallback.=20Exposed=20on=20the=20OPC=20UA=20e?= =?UTF-8?q?quipment=20node=20under=20the=20OPC=2040010-standard=20Identifi?= =?UTF-8?q?cation=20sub-folder=20per=20the=20category=20=E2=86=92=20folder?= =?UTF-8?q?=20mapping=20in=20schemas/docs/format-decisions.md=20D10.=20Dec?= =?UTF-8?q?isions=20#138=20(`=5Fbase`=20class=20with=20extends=20inheritan?= =?UTF-8?q?ce,=20references=20OPC=2040010=20+=20Part=209=20+=20ISO=2022400?= =?UTF-8?q?=20+=20handoff=20canonical=20state=20vocabulary)=20and=20#139?= =?UTF-8?q?=20(Equipment=20table=20identity=20columns)=20capture=20the=20r?= =?UTF-8?q?ationale.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/v2/admin-ui.md | 1 + docs/v2/config-db-schema.md | 14 ++++++++++++++ docs/v2/plan.md | 2 ++ 3 files changed, 17 insertions(+) diff --git a/docs/v2/admin-ui.md b/docs/v2/admin-ui.md index 8cfb1aa..f088495 100644 --- a/docs/v2/admin-ui.md +++ b/docs/v2/admin-ui.md @@ -261,6 +261,7 @@ The Drivers/Devices/Equipment/Tags tabs are **read-only views** of the published Per-equipment view. Form sections: +- **OPC 40010 Identification panel** (per the `_base` equipment-class template): operator-set static metadata exposed as OPC UA properties on the equipment node's `Identification` sub-folder — Manufacturer (required), Model (required), SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, AssetLocation (free-text supplementary to UNS path), ManufacturerUri (URL), DeviceManualUri (URL). Manufacturer + Model are required because the `_base` template declares them as `isRequired: true`; the rest are optional and can be filled in over time. Drivers that can read fields dynamically (e.g. FANUC `cnc_sysinfo()` returning `SoftwareRevision`) override the static value at runtime; otherwise the operator-set value flows through. - **Identifiers panel**: all five identifiers, with explicit purpose labels and copy-to-clipboard buttons - `ZTag` — editable; live fleet-wide uniqueness check via `ExternalIdReservation` (warns if value is currently held by another EquipmentUuid; cannot save unless reservation is released first) - `MachineCode` — editable; live within-cluster uniqueness check diff --git a/docs/v2/config-db-schema.md b/docs/v2/config-db-schema.md index 82b70b3..ae4697a 100644 --- a/docs/v2/config-db-schema.md +++ b/docs/v2/config-db-schema.md @@ -354,6 +354,18 @@ CREATE TABLE dbo.Equipment ( ZTag nvarchar(64) NULL, -- ERP equipment id. Unique fleet-wide. Primary identifier for browsing in Admin UI. SAPID nvarchar(64) NULL, -- SAP PM equipment id. Unique fleet-wide. + -- OPC 40010 Machinery Identification fields (per the `_base` equipment-class template in the schemas repo) + -- All nullable so equipment can be added before identity is fully captured; populated over time. + Manufacturer nvarchar(64) NULL, -- OPC 40010 Manufacturer + Model nvarchar(64) NULL, -- OPC 40010 Model + SerialNumber nvarchar(64) NULL, -- OPC 40010 SerialNumber + HardwareRevision nvarchar(32) NULL, -- OPC 40010 HardwareRevision + SoftwareRevision nvarchar(32) NULL, -- OPC 40010 SoftwareRevision (some drivers can read dynamically; this is the operator-set fallback) + YearOfConstruction smallint NULL, -- OPC 40010 YearOfConstruction + AssetLocation nvarchar(256) NULL, -- OPC 40010 Location, free-text supplementary to UNS path (e.g. "Bay 3, Row 12") + ManufacturerUri nvarchar(512) NULL, -- OPC 40010 ManufacturerUri + DeviceManualUri nvarchar(512) NULL, -- OPC 40010 DeviceManual (URL) + EquipmentClassRef nvarchar(128) NULL, -- nullable hook for future schemas-repo template ID Enabled bit NOT NULL DEFAULT 1 ); @@ -395,6 +407,8 @@ CREATE INDEX IX_Equipment_Generation_MachineCode All five are exposed as **OPC UA properties** on the equipment node so external systems can resolve equipment by whichever identifier they natively use, without needing a sidecar lookup service. +**OPC 40010 Machinery identity columns**: `Manufacturer`, `Model`, `SerialNumber`, `HardwareRevision`, `SoftwareRevision`, `YearOfConstruction`, `AssetLocation`, `ManufacturerUri`, `DeviceManualUri` are operator-set static metadata exposed as OPC UA properties on the equipment node's `Identification` sub-folder per OPC UA Companion Spec OPC 40010 (Machinery). Drivers that can read these dynamically (e.g. FANUC `cnc_sysinfo()` returns the software revision) override the static value at runtime; for everything else, the operator-set value flows through. The `_base` equipment-class template in the schemas repo declares these as required identity signals (`Manufacturer`, `Model` required; the rest optional) — every equipment-class template inherits the set via `extends: "_base"`. + **UUID immutability**: `sp_ValidateDraft` rejects a generation if any `(EquipmentId, EquipmentUuid)` pair conflicts with the same `EquipmentId` in any prior generation of the same cluster. Once an EquipmentId is published with a UUID, that UUID is locked for the life of the cluster. Operators can rename Area/Line/Name and edit MachineCode/ZTag/SAPID freely; the UUID stays. **UNS validation** (in `sp_ValidateDraft` and Admin UI): diff --git a/docs/v2/plan.md b/docs/v2/plan.md index 23df94d..4d46463 100644 --- a/docs/v2/plan.md +++ b/docs/v2/plan.md @@ -902,6 +902,8 @@ Each step leaves the system runnable. The generic extraction is effectively free | 135 | TwinCAT XAR runs only in a dedicated VM on the integration host; developer machines do NOT run XAR locally | The 7-day trial reactivation needs centralized management; the VM is shared infrastructure. Galaxy is the inverse — runs only on developer machines (Aveva license scoping), not on integration host | 2026-04-17 | | 136 | Consumer cutover (ScadaBridge / Ignition / System Platform IO) is OUT of v2 scope | Owned by a separate integration / operations team. OtOpcUa team's scope ends at Phase 5 (all drivers built, all stability protections in place, full Admin UI shipped including ACL editor). Cutover sequencing, validation methodology, rollback procedures, and Aveva-pattern validation for tier 3 are the integration team's deliverables, tracked in 3-year-plan handoff §"Rollout Posture" and corrections doc §C5 | 2026-04-17 | | 137 | Dev env credentials documented openly in `dev-environment.md`; production uses Integrated Security / gMSA per decision #46 | Dev defaults are not secrets — they're convenience. Production never uses these values; documented separation prevents leakage | 2026-04-17 | +| 138 | Every equipment-class template extends a shared `_base` class providing universal cross-machine metadata (identity, state, alarm summary, optional production context) | References OPC UA Companion Spec OPC 40010 (Machinery) for the Identification component + MachineryOperationMode enum, OPC UA Part 9 for alarm summary fields, ISO 22400 for KPI inputs (TotalRunSeconds, TotalCycles), 3-year-plan handoff §"Canonical Model Integration" for the canonical state vocabulary. Inheritance via `extends` field on the equipment-class JSON Schema. Avoids per-class drift in identity / state / alarm field naming and ensures every machine in the estate exposes the same baseline metadata regardless of vendor or protocol. `_base` lives in `3yearplan/schemas/classes/_base.json` (temporary location until the dedicated `schemas` repo is created) | 2026-04-17 | +| 139 | Equipment table extended with OPC 40010 identity columns (Manufacturer, Model, SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, AssetLocation, ManufacturerUri, DeviceManualUri) all nullable so equipment can be added before identity is fully captured | First-class columns rather than a JSON blob because these fields are universal (every machine has them) and need to be queryable / searchable in the Admin UI. Manufacturer and Model are declared `isRequired: true` in `_base.json` and the Admin UI flags equipment that lacks them; the rest are optional. Drivers that can read these dynamically (FANUC, Beckhoff, etc.) override the static value at runtime; static value is the fallback. Exposed on the OPC UA node under the OPC 40010-standard `Identification` sub-folder | 2026-04-17 | ## Reference Documents