Files
3yearplan/schemas/classes/fanuc-cnc.json
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

92 lines
5.5 KiB
JSON

{
"$schema": "../format/equipment-class.schema.json",
"classId": "fanuc-cnc",
"extends": "_base",
"version": "0.1.0",
"displayName": "FANUC CNC",
"description": "FANUC CNC machine tools (mills, lathes, machining centers) accessed via FOCAS2. Extends `_base` for cross-machine identity / state / alarm metadata; adds CNC-specific axis, spindle, program, and PMC signals. Pilot equipment class per OtOpcUa corrections doc D1 — chosen because the FOCAS driver already exposes a fixed pre-defined node hierarchy (lmxopcua/docs/v2/driver-specs.md §7) which is essentially a class template already; this file formalizes it.",
"vendor": "FANUC",
"applicability": {
"drivers": ["Focas"],
"models": ["0i-F", "0i-D", "30i-B", "31i-B", "32i-B"]
},
"signals": [
{
"name": "SeriesNumber",
"category": "Identity",
"dataType": "String",
"description": "CNC series read dynamically from the controller (e.g. '0i-F'). From cnc_sysinfo(). May differ from the operator-set Model if firmware reports a different series — useful for catching configuration drift.",
"isRequired": true
},
{ "name": "MaxAxes", "category": "Identity", "dataType": "Int32", "description": "Maximum axes supported by this CNC. From cnc_sysinfo()." },
{ "name": "AxisCount", "category": "Identity", "dataType": "Int32", "description": "Active axis count. From cnc_rdaxisname()." },
{ "name": "RunState", "category": "Status", "dataType": "Int32", "description": "FANUC native run state — 0=STOP, 1=HOLD, 2=START, 3=MSTR. From cnc_statinfo(). Layer 3 derives the canonical Running/Idle/Faulted state (in `_base.stateModel`) primarily from this signal." },
{ "name": "Mode", "category": "Status", "dataType": "Int32", "description": "0=MDI, 1=AUTO, 3=EDIT, 4=HANDLE, 5=JOG, 7=REF. From cnc_statinfo(). Maps to `_base.OperationMode` enum at Layer 3." },
{ "name": "MotionState", "category": "Status", "dataType": "Int32", "description": "0=idle, 1=MOTION, 2=DWELL, 3=WAIT. From cnc_statinfo()." },
{ "name": "EmergencyStop", "category": "Status", "dataType": "Boolean", "description": "From cnc_statinfo()." },
{ "name": "AlarmActive", "category": "Status", "dataType": "Int32", "description": "Bitmask of active alarm categories. From cnc_statinfo(). Layer 3 derives `_base.HasActiveAlarms` and `_base.HighestActiveAlarmSeverity` from this and cnc_rdalmmsg() detail." },
{
"name": "AxisAbsolutePosition",
"category": "Position",
"dataType": "Float64",
"unit": "mm",
"isArray": true,
"arrayDimension": 32,
"description": "Per-axis absolute position. Indexed by axis number. From cnc_absolute(). FANUC scaled-integer source converted via cnc_getfigure().",
"scaling": { "method": "DecimalPlaces", "decimalPlaces": 3 }
},
{
"name": "AxisMachinePosition",
"category": "Position",
"dataType": "Float64",
"unit": "mm",
"isArray": true,
"arrayDimension": 32,
"description": "Per-axis machine position. From cnc_machine().",
"scaling": { "method": "DecimalPlaces", "decimalPlaces": 3 }
},
{
"name": "ActualFeedRate",
"category": "Velocity",
"dataType": "Float64",
"unit": "mm/min",
"description": "Actual feed rate. From cnc_actf()."
},
{
"name": "SpindleActualSpeed",
"category": "Velocity",
"dataType": "Float64",
"unit": "rpm",
"isArray": true,
"arrayDimension": 8,
"description": "Per-spindle actual speed. From cnc_acts() / cnc_acts2()."
},
{
"name": "SpindleLoad",
"category": "Process",
"dataType": "Float64",
"unit": "%",
"isArray": true,
"arrayDimension": 8,
"description": "Per-spindle load percentage. From cnc_rdspmeter(). FOCAS2."
},
{ "name": "MainProgramNumber", "category": "Process", "dataType": "Int32", "description": "From cnc_rdprgnum(). Source for `_base.CurrentRecipe` at Layer 3 if the site uses program numbers as recipes." },
{ "name": "RunningProgramNumber", "category": "Process", "dataType": "Int32", "description": "From cnc_rdprgnum()." },
{ "name": "RunningProgramName", "category": "Process", "dataType": "String", "description": "Full program path/name. From cnc_exeprgname(). FOCAS2." },
{ "name": "SequenceNumber", "category": "Process", "dataType": "Int32", "description": "Current N-number. From cnc_rdseqnum()." },
{ "name": "PartsCount", "category": "Counter", "dataType": "Int64", "description": "Parts produced. From cnc_rdparam(6711/6712). Source for `_base.TotalCycles` at Layer 3." }
],
"alarms": [
{ "alarmId": "ps-alarm", "displayName": "Program/Setup Alarm", "severity": "High", "description": "P/S alarm category." },
{ "alarmId": "ot-alarm", "displayName": "Overtravel Alarm", "severity": "Critical", "description": "OT alarm category — axis overtravel." },
{ "alarmId": "sv-alarm", "displayName": "Servo Alarm", "severity": "Critical", "description": "Servo subsystem alarm." }
],
"stateModel": {
"states": ["Running", "Idle", "Faulted", "Starved", "Blocked"],
"derivationNotes": "Derivation lives at Layer 3 (System Platform / Ignition), not in OtOpcUa. Suggested mapping (informational): RunState=2 (START) AND MotionState=1 (MOTION) AND AlarmActive=0 → Running; RunState=0 (STOP) OR RunState=1 (HOLD) → Idle; AlarmActive≠0 OR EmergencyStop=true → Faulted; Starved/Blocked are inferred from upstream/downstream signals not exposed by FOCAS itself."
}
}