MiravoMiravo

Asset Models

Define one asset type in an `.asset.yaml` file: parameters, members, methods, lifecycle, and faults.

Write a new asset model when no built-in model matches the equipment you need.

Technical details

Start with the smallest valid model

schema_version: "2"
model:
  name: my-sensor
  description: "Temperature sensor"

parameters:
  temp_center:
    type: float
    default: 22
    unit: degC

members:
  temperature:
    kind: variable
    data_type: Double
    access: read
    unit: degC
    generator:
      type: noise
      center: "$param.temp_center"
      stddev: 0.5

Save the file as my-sensor.asset.yaml, then inspect it with miravo models inspect.

miravo models inspect ./my-sensor.asset.yaml

Author in dependency order

  1. Set model.name and any parameters.
  2. Declare members in the order they must be evaluated.
  3. Add methods if external clients should write members or parameters.
  4. Add lifecycle stages and faults once the process path is right.

Members are evaluated in declaration order. A member can read an earlier member in the same tick, but not a later one.

Integer members

Members with an integer data_type (Int32, UInt16, UInt32) publish whole numbers on every protocol and in the admin API. Values truncate toward zero and clamp to the type range. Generators keep their own fractional state, so an integrator still accumulates smoothly.

Pick the value source

NeedUse
Process value that changes every tickgenerator
Runtime state such as lifecycle stage or fault healthbinding
A writable control pointreadwrite or write member plus methods
Static metadataproperty member

Read another asset through an input port

A model cannot read another asset's members directly. Instead, declare a numeric input port on the model and read it with input: { port: name }. Each template then wires the port to a member of another asset.

inputs:
  network_supply_temp:
    default: 92
    unit: degC
    description: "Supply temperature leaving the plant."

members:
  primary_supply_temp:
    kind: variable
    data_type: Double
    access: read
    unit: degC
    generator:
      type: first-order-lag
      tau: 60
      input: { port: network_supply_temp }
  • A port name follows the identifier rules and cannot match a member or parameter name.
  • A bound port reads the source member's process value (before observation effects) from the previous scheduler substep. Results do not depend on asset order. A cycle between assets is valid and adds one substep of lag.
  • An unbound port reads default. So does a port whose source asset or member is gone, for example after miravo remove. On the first substep a bound port reads the source's initial value, so delays and lags start from the real signal.
  • miravo spawn leaves every port unbound. Bindings come from the template (see Templates).
  • miravo models inspect <id> lists the ports. The asset detail API (GET /api/assets/{id}) returns each port's binding and current value.

Bind runtime state

fault_active:
  kind: variable
  data_type: Boolean
  access: read
  binding:
    type: fault-active

availability_state:
  kind: variable
  data_type: String
  access: read
  binding:
    type: availability-state
    member: speed_feedback
    operator: ">"
    threshold: 50

The availability-state binding also takes running_state, stopped_state, and faulted_state labels. They default to running, stopped, and faulted.

Add observation effects after process truth

discharge_pressure:
  kind: variable
  data_type: Double
  access: read
  unit: bar
  eu_range: [0, 12]
  generator:
    type: correlated
    source: speed_feedback
    factor: 0.004
    offset: 1.5
  observation_effects:
    - type: white_noise
      strength: 0.01
    - type: drift
      tau: 1800
      sigma: 0.02
    - type: quantize
      bits: 14
    - type: deadband
      absolute: 0.05

Use observation_effects only on numeric read variables. The schema rejects readwrite and write members and non-numeric types.

Generators: Observation effects lists every effect type, its parameters, the required order, and the lint thresholds.

Lifecycle and fault timing

Lifecycle and fault timing run on simulated time. lifecycle.running_member can name a Boolean member whose previous-step value gates operating hours. Stage transitions blend over 60 simulated seconds. Faults use trigger.rate_per_hour and the effect fields duration_s, onset_s, and recovery_s. See Lifecycle and faults for rates and ramps.

Station production effects

A fault can set production_effect to stop, { derate: 0.5 } (a factor in (0, 1]), or { scrap: 0.3 } (an addition in [0, 1]). A lifecycle stage can set scrap_rate_add >= 0. These affect production only for assets configured as line stations.

Miravo appends the station members to each station instance, not to the shared model. Do not declare those member names in your model.

Reference

Field or blockNotes
schema_versionMust be "2"
modelname (identifier), optional description, optional namespace
parametersTypes float, int, string, bool, each with a default
inputsOptional numeric input ports with default, optional unit and description. Read with input: { port: name }.
membersAt least one. Declaration order matters.
methodsRuntime actions: set-members, set-parameters, clear-faults, reset-lifecycle
binding.typethreshold, lifecycle-stage, health-state, fault-active, fault-count, active-fault-code, availability-state
observation_effects.typewhite_noise, drift, outlier, gap, noise_burst, quantize, deadband, stuck

Was this page useful?

Last updated on