Files
3yearplan/schemas
Joseph Doherty cd85159951 Add _base equipment-class template for universal cross-machine metadata that every machine in the OtOpcUa estate exposes regardless of vendor, protocol, or machine type. References OPC UA Companion Spec OPC 40010 (Machinery) for the Identification component (Manufacturer, Model, ProductInstanceUri, SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, ManufacturerUri, DeviceManual, AssetLocation) plus the MachineryOperationMode enum (Auto, Manual, Maintenance, Service, Setup, Other), OPC UA Part 9 for the alarm summary fields (HasActiveAlarms, ActiveAlarmCount, HighestActiveAlarmSeverity), ISO 22400 for the lifetime counter fields (TotalRunSeconds, TotalCycles) that feed Availability + Performance KPIs at Layer 3, and the 3-year-plan handoff §"Canonical Model Integration" for the canonical state vocabulary (Running / Idle / Faulted / Starved / Blocked) declared in _base.stateModel. Includes the OtOpcUa five-identifier set (EquipmentUuid, MachineCode, ZTag, SAPID, plus DeviceClass = EquipmentClassRef) so every machine surfaces the join keys downstream consumers need; ConnectionState + LastDataTimestamp + DriverType for driver-side observability that does not require any particular equipment-protocol feature; optional production context (CurrentWorkOrder, CurrentPartNumber, CurrentRecipe, CurrentOperator, CurrentShift) marked isRequired: false since not every machine type surfaces these. Plus two universal alarm definitions (communication-loss, data-stale) that apply to every equipment regardless of class.
Equipment-class.schema.json gains an `extends` field for class inheritance — child classes inherit signals, alarms, and stateModel from the parent and can add new ones or override individual entries by name. Convention: `_` prefix on classId marks an abstract base class (e.g. `_base`) intended only to be extended, not assigned directly to equipment via Equipment.EquipmentClassRef.

FANUC CNC class updated to extends: "_base"; redundant identity signals (Version, ActiveAlarmCount) removed since they're now in the base; remaining FANUC-specific signals updated with cross-references showing how they feed into the base signals at Layer 3 (RunState → canonical Running/Idle/Faulted derivation; AlarmActive → HasActiveAlarms / HighestActiveAlarmSeverity; PartsCount → TotalCycles; MainProgramNumber → CurrentRecipe).

Format-decisions.md adds D9 (rationale for `_base` + `extends` inheritance, with references to OPC 40010 / Part 9 / ISO 22400 / handoff) and D10 (signal `category` drives OPC UA folder placement, per OPC 40010 Identification + Status pattern, with a category-to-folder mapping table).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:54:17 -04:00
..
Add _base equipment-class template for universal cross-machine metadata that every machine in the OtOpcUa estate exposes regardless of vendor, protocol, or machine type. References OPC UA Companion Spec OPC 40010 (Machinery) for the Identification component (Manufacturer, Model, ProductInstanceUri, SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, ManufacturerUri, DeviceManual, AssetLocation) plus the MachineryOperationMode enum (Auto, Manual, Maintenance, Service, Setup, Other), OPC UA Part 9 for the alarm summary fields (HasActiveAlarms, ActiveAlarmCount, HighestActiveAlarmSeverity), ISO 22400 for the lifetime counter fields (TotalRunSeconds, TotalCycles) that feed Availability + Performance KPIs at Layer 3, and the 3-year-plan handoff §"Canonical Model Integration" for the canonical state vocabulary (Running / Idle / Faulted / Starved / Blocked) declared in _base.stateModel. Includes the OtOpcUa five-identifier set (EquipmentUuid, MachineCode, ZTag, SAPID, plus DeviceClass = EquipmentClassRef) so every machine surfaces the join keys downstream consumers need; ConnectionState + LastDataTimestamp + DriverType for driver-side observability that does not require any particular equipment-protocol feature; optional production context (CurrentWorkOrder, CurrentPartNumber, CurrentRecipe, CurrentOperator, CurrentShift) marked isRequired: false since not every machine type surfaces these. Plus two universal alarm definitions (communication-loss, data-stale) that apply to every equipment regardless of class.
2026-04-17 12:54:17 -04:00
Add _base equipment-class template for universal cross-machine metadata that every machine in the OtOpcUa estate exposes regardless of vendor, protocol, or machine type. References OPC UA Companion Spec OPC 40010 (Machinery) for the Identification component (Manufacturer, Model, ProductInstanceUri, SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, ManufacturerUri, DeviceManual, AssetLocation) plus the MachineryOperationMode enum (Auto, Manual, Maintenance, Service, Setup, Other), OPC UA Part 9 for the alarm summary fields (HasActiveAlarms, ActiveAlarmCount, HighestActiveAlarmSeverity), ISO 22400 for the lifetime counter fields (TotalRunSeconds, TotalCycles) that feed Availability + Performance KPIs at Layer 3, and the 3-year-plan handoff §"Canonical Model Integration" for the canonical state vocabulary (Running / Idle / Faulted / Starved / Blocked) declared in _base.stateModel. Includes the OtOpcUa five-identifier set (EquipmentUuid, MachineCode, ZTag, SAPID, plus DeviceClass = EquipmentClassRef) so every machine surfaces the join keys downstream consumers need; ConnectionState + LastDataTimestamp + DriverType for driver-side observability that does not require any particular equipment-protocol feature; optional production context (CurrentWorkOrder, CurrentPartNumber, CurrentRecipe, CurrentOperator, CurrentShift) marked isRequired: false since not every machine type surfaces these. Plus two universal alarm definitions (communication-loss, data-stale) that apply to every equipment regardless of class.
2026-04-17 12:54:17 -04:00
Add _base equipment-class template for universal cross-machine metadata that every machine in the OtOpcUa estate exposes regardless of vendor, protocol, or machine type. References OPC UA Companion Spec OPC 40010 (Machinery) for the Identification component (Manufacturer, Model, ProductInstanceUri, SerialNumber, HardwareRevision, SoftwareRevision, YearOfConstruction, ManufacturerUri, DeviceManual, AssetLocation) plus the MachineryOperationMode enum (Auto, Manual, Maintenance, Service, Setup, Other), OPC UA Part 9 for the alarm summary fields (HasActiveAlarms, ActiveAlarmCount, HighestActiveAlarmSeverity), ISO 22400 for the lifetime counter fields (TotalRunSeconds, TotalCycles) that feed Availability + Performance KPIs at Layer 3, and the 3-year-plan handoff §"Canonical Model Integration" for the canonical state vocabulary (Running / Idle / Faulted / Starved / Blocked) declared in _base.stateModel. Includes the OtOpcUa five-identifier set (EquipmentUuid, MachineCode, ZTag, SAPID, plus DeviceClass = EquipmentClassRef) so every machine surfaces the join keys downstream consumers need; ConnectionState + LastDataTimestamp + DriverType for driver-side observability that does not require any particular equipment-protocol feature; optional production context (CurrentWorkOrder, CurrentPartNumber, CurrentRecipe, CurrentOperator, CurrentShift) marked isRequired: false since not every machine type surfaces these. Plus two universal alarm definitions (communication-loss, data-stale) that apply to every equipment regardless of class.
2026-04-17 12:54:17 -04:00

schemas — Canonical OT Equipment Definitions

Status: DRAFT — initial seed contributed by the OtOpcUa team (lmxopcua/docs/v2/acl-design.md, lmxopcua/docs/v2/plan.md decisions #112, #115, corrections doc D1+D2). Ownership of this content is TBD — should be assigned to a cross-team authority since it's consumed by OT and IT systems alike. The future owner team should treat this seed as a starting point, not a finished spec.

Temporary location: this seed lives at 3yearplan/schemas/ as a sub-tree of the 3-year-plan repo because Gitea's push-to-create is disabled and creating the dedicated schemas repo requires a manual UI step. Once the dedicated repo is created (proposed: gitea.dohertylan.com/dohertj2/schemas) and an owner team is named, this content should migrate over and references update accordingly. Until then, treat this directory as the canonical location for the seed.

Purpose

Single source of truth for the org's canonical OT equipment definitions:

  1. UNS hierarchy — the per-site Unified Namespace subtree (Enterprise / Site / Area / Line / Equipment) per the 3-year-plan handoff §UNS Naming Hierarchy
  2. Equipment-class templates — per-class declarations of which raw signals each equipment type exposes (FANUC CNCs surface these; Modbus PLCs surface those; etc.)
  3. Type vocabulary — the canonical machine-state values (Running / Idle / Faulted / Starved / Blocked) and any other shared enumerations consumers need

Who consumes this

Three surfaces per the 3-year-plan handoff §"Canonical Model Integration":

Consumer How
OtOpcUa equipment namespace At deploy/config time, OtOpcUa nodes fetch the equipment-class template referenced by Equipment.EquipmentClassRef and use it to validate the operator-configured tag set. Drift = config validation error
Redpanda topics + Protobuf schemas Equipment-class templates derive Protobuf message definitions for canonical events (equipment.state.transitioned, etc.)
dbt curated layer in Snowflake Same templates derive column definitions and dimension tables for the curated analytics model

OtOpcUa is one consumer of three. Decisions about format, structure, and naming live with the schemas-repo owner team (TBD), not with any one consumer.

Format

JSON Schema (Draft 2020-12) authored in this repo; Protobuf code-generated for wire serialization where needed (per OtOpcUa corrections doc D2 recommendation, blessed by the OtOpcUa team but pending schemas-repo team review).

Why JSON Schema as the authoring format:

  • Idiomatic for .NET (System.Text.Json + JsonSchema.Net) — OtOpcUa reads templates with no extra dependencies
  • Idiomatic for CI tooling (every CI runner can jq / validate JSON Schema without extra toolchain)
  • Supports validation at multiple layers: operator-visible Admin UI errors in OtOpcUa, schemas-repo CI gates, downstream consumer runtime validation
  • Better authoring experience than Protobuf (binary format, .proto compiler, poor merge story)
  • Where wire-format efficiency matters (Redpanda events), code-generate Protobuf from the JSON Schema source. One-way derivation is simpler than bidirectional sync.

Structure

schemas/
├── README.md                                    This file
├── CONTRIBUTING.md                              How to add a new class, validate, PR process
├── format/                                      JSON Schemas defining the format of everything below
│   ├── equipment-class.schema.json              Shape of an equipment-class template
│   ├── uns-subtree.schema.json                  Shape of a per-site UNS subtree definition
│   └── tag-definition.schema.json               Shape of an individual tag declaration inside a template
├── classes/                                     Equipment-class templates
│   └── fanuc-cnc.json                           Pilot class per OtOpcUa corrections D1
├── uns/                                         Per-site UNS subtree definitions
│   └── example-warsaw-west.json                 Worked example
└── docs/
    ├── overview.md                              What this repo is, who uses it, lifecycle
    ├── format-decisions.md                      Why JSON Schema, structure rationale, Protobuf derivation
    └── consumer-integration.md                  How each of the 3 consumers integrates

Lifecycle

  1. Author — humans edit JSON files in this repo, validated against the schemas in format/ by the CI gate
  2. Publish — merging to main makes the new content the authoritative version; semver tag on each release
  3. Consume — each consumer pulls a specific tagged version (or main for staging environments) and integrates per docs/consumer-integration.md

The current state has no consumers actively reading from this repo — content is seed-only. First wiring happens in OtOpcUa Phase 1+ when Equipment.EquipmentClassRef validation lands (see lmxopcua/docs/v2/plan.md decision #112).

Open Questions

Owner-team-decisions (not for OtOpcUa or any single consumer to make alone):

  • Repo ownership and review process: who owns this repo? PR review SLA? Format changes need who to sign off?
  • Versioning policy: semver per release? Per-class versioning vs whole-repo versioning? How do consumers pin versions?
  • Backward-compatibility policy: when a class adds a new required signal, do all existing equipment in OtOpcUa's central config DB need to be updated atomically? Or graceful degradation?
  • Cross-class shared types: how does a Position measurement (used by both FANUC CNC and a Beckhoff axis) avoid duplicate definitions?
  • Pilot class scope: FANUC CNC chosen per OtOpcUa corrections D1 because FOCAS already has a fixed pre-defined hierarchy. Confirm with the schemas-repo team that this is the right starting class.
  • Enterprise shortname (currently ent placeholder) — the UNS subtree definitions reference an Enterprise segment; the canonical value comes from organizational naming authority.

References

  • 3-year-plan handoff: gitea.dohertylan.com/dohertj2/3yearplanhandoffs/otopcua-handoff.md §"UNS Naming Hierarchy" + §"Canonical Model Integration" + §"Digital Twin Touchpoints"
  • OtOpcUa corrections doc: gitea.dohertylan.com/dohertj2/3yearplanhandoffs/otopcua-corrections-2026-04-17.md §B2 (schemas-repo dependencies) + §D1 (pilot class) + §D2 (format)
  • OtOpcUa v2 plan: gitea.dohertylan.com/dohertj2/lmxopcuadocs/v2/plan.md decisions #108115 + §"UNS naming hierarchy"