Skip to content

Core Concepts

Understand Miravo's core mental model: models, templates, members, generators, the tick loop, Unified Namespace, lifecycle stages, and the asset graph.

A model (.twin.yaml) defines an asset type: what it measures, how it behaves, and what can go wrong. Think of it as a class definition for an industrial asset.

Each model declares:

  • Parameters — Tunable constants (rated speed, capacity, power rating)
  • Members — The signals and properties the asset exposes (temperature, pressure, speed, state)
  • Generators — Math that drives member values each tick (sine waves, random walks, thermal lag)
  • Methods — Executable actions (Start, Stop, SetSpeed, ResetFault)
  • Lifecycle — Degradation stages the asset progresses through over operating hours
  • Faults — Failure modes with triggers and effects

One model can be instantiated many times with different parameter overrides. A centrifugal-pump model becomes pump-001, pump-002, etc., each with slightly different rated speeds.

A template (.miravo.yaml) composes models into a structured plant topology. Templates define:

  • Namespace — Enterprise and site names for UNS topic hierarchy
  • Areas and lines — ISA-95-style organizational structure
  • Twin assignments — Which models go where, how many, with what parameter overrides
  • Settings — Tick interval, time multiplier, seed
namespace:
enterprise: AcmeCorp
site: detroit-plant
areas:
- name: production
lines:
- name: line-1
twins:
- model: centrifugal-pump
count: 3
variation: 0.05

Members are the signals and properties an asset exposes. Each member has a kind, data type, and access level:

KindPurpose
variableDynamic values that change each tick (sensor readings, process values)
propertyStatic metadata (serial number, model number, rated capacity)

Use variable for values that change each tick. Use property for static metadata like serial numbers or rated capacity that doesn’t change at runtime.

Data types: Double, Float, Int32, UInt16, UInt32, Boolean, String.

Access levels: read, readwrite, write.

Generators produce member values on each tick. Miravo ships 18 generator types:

  • Source generatorssine, noise, random-walk, step, ramp, mean-reverting-noise, timetable, state-machine
  • Dynamic generatorsfirst-order-lag, integrator, transport-delay, slew-rate-limiter, second-order, hysteresis-relay, weighted-sum, gate
  • Compositehealth-dependent, correlated

Each generator reads its configuration from the model and produces a numeric (or string) value every tick. Generators can reference other members, parameters, or embed sub-generators.

Miravo runs on a fixed-interval tick loop (default: 1000ms). Each tick:

  1. Evaluate all generators in member declaration order
  2. Apply lifecycle effects (multiplier + offset)
  3. Apply fault effects (spike, multiplier, offset)
  4. Update the asset graph
  5. Emit the graph snapshot and delta to protocol adapters

Protocol adapters (MQTT, OPC UA, and upcoming protocols like Modbus TCP and Sparkplug B) receive the updated data and publish/update their outputs.

Every member value lives at a path in the asset graph. The MQTT adapter publishes each member as an individual topic:

{enterprise}/{site}/{area}/{line}/{instance}/{member}

For example: AcmeCorp/detroit-plant/production/line-1/pump-001/discharge_pressure

OPC UA mirrors the same hierarchy as folder nodes with typed instance objects at the leaf.

Lifecycle stages model long-term degradation. An asset progresses through stages (healthy, degraded, critical) based on operating hours. Each stage applies effects to member values.

Faults model failure modes. Triggers fire based on lifecycle stage, sensor conditions, or probability. Effects include value spikes, multipliers, and offsets with configurable duration.

The asset graph is the runtime source of truth. It holds all active instances with their current member values, parameters, lifecycle stage, and active faults. Protocol adapters read from the graph — they never compute values themselves.