Description
IAES — Industrial Asset Event Standard
> A vendor-neutral event format for industrial asset measurements, diagnoses, and maintenance intents.







Industrial systems speak different languages. A vibration sensor outputs raw waveforms. An AI model outputs health scores. SAP expects maintenance notifications. PI System expects tag values. MaintainX expects user variables.
IAES provides the neutral layer in between — one event format that any producer can emit and any consumer can understand.
Sensors --> Intelligence --> IAES --> Connectors --> Enterprise Systems
Part of IAES
The standard ships as four packages that version together. **The first two
numbers of a package version are the specification it implements** — 2.0.x
implements IAES 2.0.
| Runtime | Package | Install |
|—|—|—|
| TypeScript / JavaScript | @iaes/sdk | npm install @iaes/sdk |
| Python | iaes | pip install iaes |
| Node-RED | node-red-contrib-iaes | npm install node-red-contrib-iaes |
| n8n | n8n-nodes-iaes | npm install n8n-nodes-iaes |
Specification, JSON Schemas and governance: iaes.dev.
Install
pip install iaes # Python
npm install @iaes/sdk # TypeScript / Node.js
npm install node-red-contrib-iaes # Node-RED
Publish Events
The SDK includes a Client that sends IAES events to any compliant endpoint via HTTPS.
Python:
from iaes import Client, AssetMeasurementclient = Client("https://your-endpoint.example.com", api_key="your-key")
event = AssetMeasurement(
asset_id="MOTOR-001",
measurementtype="vibrationvelocity",
value=4.2,
unit="mm/s",
source="acme.sensors.plant1",
)
result = client.publish(event)
TypeScript:
import { IaesClient, AssetMeasurement } from "@iaes/sdk";const client = new IaesClient("https://your-endpoint.example.com", {
apiKey: "your-key",
});
const event = new AssetMeasurement({
asset_id: "MOTOR-001",
measurementtype: "vibrationvelocity",
value: 4.2,
unit: "mm/s",
source: "acme.sensors.plant1",
});
const result = await client.publish(event);
The endpoint URL is any IAES-compliant receiver — your own backend, a cloud broker, or a third-party integration.
Examples
Vibration measurement
from iaes import AssetMeasurementevent = AssetMeasurement(
asset_id="MOTOR-001",
measurementtype="vibrationvelocity",
value=4.2,
unit="mm/s",
source="acme.sensors.plant1",
units_qualifier="rms", # ISO 17359
samplingratehz=25600,
)
payload = event.to_dict() # IAES wire format, ready for json.dumps()
import { AssetMeasurement } from "@iaes/sdk"const event = new AssetMeasurement({
asset_id: "MOTOR-001",
measurementtype: "vibrationvelocity",
value: 4.2,
unit: "mm/s",
source: "acme.sensors.plant1",
units_qualifier: "rms",
samplingratehz: 25600,
})
const payload = JSON.stringify(event) // toJSON() called automatically
Energy / power quality
from iaes import AssetMeasurementpf_event = AssetMeasurement(
asset_id="SUBSTATION-A",
measurementtype="powerfactor",
value=0.82,
unit="ratio",
source="ion8650.meter_01",
)
thd_event = AssetMeasurement(
asset_id="SUBSTATION-A",
measurementtype="thdvoltage",
value=6.3,
unit="%",
source="ion8650.meter_01",
)
AI health diagnosis
from iaes import AssetHealth, Severityevent = AssetHealth(
asset_id="MOTOR-001",
health_index=0.16,
severity=Severity.CRITICAL,
failuremode="bearinginner_race",
rul_days=5,
recommended_action="Replace bearing immediately",
source="ai.vibration_model",
iso13374status="unacceptable", # ISO 13374
iso_14224={ # ISO 14224
"mechanism_code": "1.1",
"cause_code": "1",
"detection_method": "VIB",
},
)
Work order intent
from iaes import WorkOrderIntentevent = WorkOrderIntent(
asset_id="MOTOR-001",
title="Replace bearing DE — AI diagnosis critical",
priority="high",
triggeredby="aidiagnosis",
recommendedduedays=3,
source="ai.vibration_model",
sourceeventid="eventid>", # links to the diagnosis
)
Maintenance completion
from iaes import MaintenanceCompletionevent = MaintenanceCompletion(
asset_id="MOTOR-001",
workorderid="WO-2026-0042",
status="completed",
actualdurationseconds=7200,
failure_confirmed=True,
failuremode="bearinginner_race",
source="cmms.sap_pm",
)
Validate
from iaes import validate, ValidationErrortry:
validate(event.to_dict())
print("Valid IAES event")
except ValidationError as e:
print(e)
Requires: pip install iaes[validate]
Deserialize
import json
from iaes import from_dictAny IAES envelope -> correct model instance
wire = json.loads(mqtt_message)
event = from_dict(wire) # AssetMeasurement, AssetHealth, etc.
print(event.asset_id, event.value)
Event Types (v2.0)
| Event Type | Python | TypeScript | Purpose |
|————|——–|————|———|
| asset.measurement | AssetMeasurement | AssetMeasurement | Sensor reading (vibration, temperature, pressure, current, power factor, THD…) |
| asset.health | AssetHealth | AssetHealth | AI diagnosis or expert assessment (health index, fault, RUL) |
| maintenance.workorderintent | WorkOrderIntent | WorkOrderIntent | Intent to create a work order |
| maintenance.completion | MaintenanceCompletion | MaintenanceCompletion | Work order completion acknowledgment |
| asset.hierarchy | AssetHierarchy | AssetHierarchy | Asset hierarchy sync (org > plant > area > equipment) |
| sensor.registration | SensorRegistration | SensorRegistration | Sensor discovery and lifecycle |
| maintenance.sparepartusage | SparePartUsage | SparePartUsage | Spare parts consumed during maintenance |
Enums
All enums accept either the enum constant or a plain string:
AssetHealth(asset_id="M-001", severity=Severity.CRITICAL)
AssetHealth(asset_id="M-001", severity="critical") # also works
| Enum | Values |
|——|——–|
| Severity | info, low, medium, high, critical |
| MeasurementType | vibrationvelocity, vibrationacceleration, temperature, current, voltage, power, pressure, flow, speed, powerfactor, thdvoltage, thd_current, frequency, … |
| UnitsQualifier | rms, peak, peaktopeak, average, true_rms |
| ISO13374Status | unknown, normal, satisfactory, unsatisfactory, unacceptable, imminent_failure, failed |
| WorkOrderPriority | low, medium, high, emergency |
| CompletionStatus | completed, partially_completed, cancelled, deferred |
| HierarchyLevel | organization, plant, area, equipment |
| RelationshipType | parentof, childof, siblingof, dependson |
| RegistrationStatus | discovered, registered, calibrated, decommissioned |
Wire Format
Every event serializes to the same envelope structure:
{
"spec_version": "2.0",
"dataschema": "https://iaes.dev/schema/v2/asset.measurement",
"event_type": "asset.measurement",
"event_id": "a9e3c4b2-...",
"correlation_id": "3b2f9d8c-...",
"timestamp": "2026-03-08T12:00:00+00:00",
"source": "acme.sensors.plant1",
"content_hash": "8a3f9c2e1b4d7e6f",
"asset": {
"asset_id": "MOTOR-001",
"asset_name": "Motor Bomba P-101",
"plant": "Planta Norte",
"area": "Turbinas"
},
"data": {
"measurementtype": "vibrationvelocity",
"value": 4.2,
"unit": "mm/s",
"units_qualifier": "rms",
"samplingratehz": 25600
}
}
dataschema is the canonical URI of the schema the payload was written against — the SDKs derive it from event_type and omit it for a custom type that has no published schema.
content_hash is a 16-char SHA-256 prefix of the data payload, computed identically in Python and TypeScript for cross-language idempotency.
Standards referenced
IAES cites industrial standards where they supply context or a vocabulary
defined outside it. Citation is not conformance, and IAES 2.0 claims none
to ISO 13374, ISO 17359, ISO 14224 or ISO 55000.
| Document | Relationship | Normative for meaning |
|—|—|—|
| ISO 4217 | currency carries an ISO 4217 code | Yes — and the schema checks the shape, not the list |
| ISO 14224 | Context. Named for the iso_14224 object and Appendix B | No |
| ISO 17359 | Context. Named for units_qualifier and the acquisition fields | No |
| ISO 13374 series | Historical context. The attributions on iso13374status and condition_trend were withdrawn in 2.0: the values are IAES’s own vocabulary and the field names are kept for 1.x compatibility | No |
| ISO 55000 | Context for asset management | No |
Earlier IAES material described a field-level mapping to those four documents.
IAES 2.0 withdrew that claim where the correspondence had not been verified
against the cited document. The full table, including what the schemas do and
do not enforce, is in IAES_SPEC.md under References — the specification
governs. All these fields are optional; 1.x events remain valid.
Zero Dependencies
The core SDK uses only standard library. No runtime dependencies.
| | Core | Validation |
|-|——|————|
| Python | stdlib only | pip install iaes[validate] adds jsonschema |
| TypeScript | Node.js crypto only | ajv optional |
Cross-Language Compatibility
Both SDKs produce identical wire format and identical content_hash for the same data. Events created in Python validate in TypeScript and vice versa. This is tested on every commit.
Reference scenarios
One industrial story, told four times: a vibration model reads 4.2 mm/s RMS on a motor, concludes a bearing’s outer race is degrading, asks maintenance to inspect it, and a technician closes the loop. Each implementation produces the same five events — the workflow changes, the event meaning does not — and tests/testreferencescenarios.py checks all four against a single fixture on every commit.
| Implementation | The scenario | Reach for it when |
|—|—|—|
| Python | scenarios/typescript/reference-scenarios.ts | the producer is a service |
| Node-RED | scenarios/node-red/flow.json — the flow file; a real Node-RED loads it unchanged on every commit | the reading is already on the wire, at the OT boundary |
| n8n | scenarios/n8n/workflow.json — the workflow file; run.js executes its IAES nodes on every commit, and importing it into an n8n instance has not yet been done | the trigger is a webhook or a schedule |
The fixture is scenarios/fixture.json. It names which fields are volatile (a fresh event_id, the moment of emission) and why, so what is compared is what a consumer acts on.
Node-RED
node-red-contrib-iaes provides 7 nodes for visual IAES workflows:
| Node | Purpose |
|——|———|
| iaes-measurement | Create asset.measurement events from sensor inputs |
| iaes-health | Create asset.health events from AI models or expert rules |
| iaes-work-order | Create maintenance.workorderintent events |
| iaes-validate | Validate any IAES envelope against JSON Schema |
| iaes-sparkplug | Bridge Sparkplug B payloads to/from IAES format |
| iaes-publish | Publish IAES events to any compliant HTTP endpoint |
| iaes-route | Route events by type, severity, or custom expressions |
npm install node-red-contrib-iaes
Official Specification
> IAES-RFC-001 — Industrial Asset Event Model
> DOI: 10.5281/zenodo.18973217
- GOVERNANCE.md — Normative. Stewardship, compatibility policy, schema identity, and how the standard changes
- IAES-RFC-001 — Formal RFC specification
- schema/ — 8 JSON Schema files
- examples/ — 11 JSON examples
- iaes.dev — Website
Design Principles
1. Vendor neutrality — No dependency on any specific platform or system
2. Legacy compatibility — Maps cleanly to CMMS, historians, SCADA, IoT
3. Event-oriented — Each object represents something that happened
4. Complete traceability — eventid + correlationid + sourceeventid chain
5. Extensibility — data payload allows new fields without breaking consumers
System Compatibility
| System | IAES Mapping |
|——–|————-|
| SAP PM | Maintenance Notification / Order |
| PI System / AVEVA | Tag value writes / SDS streams |
| Odoo | maintenance.request |
| MaintainX | User Variables |
| Fracttal | Custom fields + OT |
| Node-RED | node-red-contrib-iaes — 7 nodes |
| MQTT / Kafka | JSON payload on any topic |
How to Cite IAES
If you use IAES in research or industrial systems, please cite:
Garza, G. (2026).
Industrial Asset Event Standard (IAES) v1.3.
Zenodo.
https://doi.org/10.5281/zenodo.18973217
BibTeX:
@software{garzaiaes2026,
author = {Garza, Gilberto},
title = {Industrial Asset Event Standard (IAES)},
version = {v1.3.0},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.18973217},
url = {https://doi.org/10.5281/zenodo.18973217}
}
ResearchGate
License
IAES is an open specification. The specification text and JSON schemas are licensed under CC BY 4.0. Implementations may use any license.
—
IAES v2.0 — September 2026