FMI Interface support

Applications that communicate with external devices are inherently difficult to test in isolation. A large number of simulation tools is available, that allow interfacing such applications with a simulated device. This enables application development, testing and evaluation in absence of an actual device. In addition simulation can easily provide information on current device state, and simulate conditions that are rare and difficult to achieve on request in a physical device (i.e., specific malfunctions). Squish supports communication to such tools using the FMI interface.

The Functional Mockup Interface is an industry standard for model exchange and co-simulation of dynamic models. It describes interface between exporters and importers of simulation units called Functional Mockup Units (FMUs). Squish has the capability to import FMUs that support FMI 2.0 CoSimulation mode. As an FMU importer, Squish has access to all variables exposed by a FMU, and is responsible for driving the simulation process. The following section introduces APIs that Squish provides to import and execute FMUs.

Full FMI 2.0 specification text can be obtained at https://www.fmi-standard.org. Squish support of FMI interface is based upon the FMI library from the JModelica platform.

FMI Overview

Note: The interface described here is not considered the final version. The details of the described API can change in the release version of the feature.

The FMI standard specifies that a FMU can contain either compiled executable code in form of a platform-specific shared object file, or a set of source code files that can be compiled by an FMI importer. Squish supports only the former.

It is not recommended to load a FMU in the same context as the AUT. To separate the FMU from any other processes, Squish provides a utility executable fmiutil. FMI functionality is available only in the application context of the fmiutil tool. It is located in Squish binary installation directory. To launch fmiutil, use the ApplicationContext startFMI() function.

ApplicationContext startFMI()

ApplicationContext startFMI(host)

ApplicationContext startFMI(host, port)

ApplicationContext startFMI(host, port, timeoutSecs)

Starts a new fmiutil instance and returns a handle to its application context.

Optionally, as first and second parameters a host and port can be specified. If these parameters are used, instead of connecting to the default host and port (as specified in the squishide's settings or on squishrunner's command line), a connection to the squishserver on the specified host and listening to the specified port will be established.

The third parameter, timeoutSecs (an integer number of seconds) can also be specified. This tells Squish how long it should be prepared to wait for the application to start before throwing an error. If specified, this value overrides squishrunner's default AUT timeout. If not specified the squishserver's default is used—this is 20 seconds, unless it has been changed. See Squish Server Settings dialog.

If you want to specify a timeout, but don't want to change the host or port, you can do so by passing an empty string as the host (which will make Squish use the configured host—localhost by default), and by passing -1 as the port.

Fmi2Import class

The Fmi2Import class is the core of the Squish FMI Interface support. It represents an FMU imported by Squish.

Fmi2Import Fmi2Import.create(filename, workingDirectory)

Fmi2Import Fmi2Import.create(filename)

This static method opens a specified FMU using the specified directory as a working directory, and returns a Fmi2Import object. If workingDirectory is not specified, a temporary directory is created in %TEMP% directory on each invocation of the method.

Fmi2Import.lastError

This read-only property holds a string describing the last error a FMU has encountered. It is set by Fmi2Import methods when returning an error.

Fmi2Import.name

Fmi2Import.identifierME

Fmi2Import.identifierCS

Fmi2Import.guid

Fmi2Import.description

Fmi2Import.author

Fmi2Import.license

Fmi2Import.version

Fmi2Import.standardVersion

Fmi2Import.generationTool

Fmi2Import.generationDate

Fmi2Import.namingConvetion

Fmi2Import.continuousStates

Fmi2Import.eventIndicators

Fmi2Import.defaultExperimentStart

Fmi2Import.defaultExperimentStop

Fmi2Import.defaultExperimentTolerance

Fmi2Import.defaultExperimentStep

These read-only properties hold meatadata for a FMU object as specified by FMI 2.0 standard.

Fmi2Import.fmuKind

This read-only property holds a value that indicates the FMI modes supported by a FMU. It can be one of:

  • Fmi2Import.KindUnknown — An unknkown FMU kind
  • Fmi2Import.KindME — A FMU that supports only ModelExchange mode
  • Fmi2Import.KindCS — A FMU that supports only CoSimulation mode
  • Fmi2Import.KindMECS — A FMU that supports both ModelExchange and CoSimulation mode

Fmi2Import.state

This read-only property holds the current state of a FMU. It can be one of:

  • Fmi2Import.Preloaded — The XML file describing the FMU was parsed, but binary model executable was not loaded yet.
  • Fmi2Import.Instantiated — The binary model executable was successfully loaded and the model was instantiated.
  • Fmi2Import.Init — The FMU has entered the initialization mode.
  • Fmi2Import.Event — The FMU is in event state. This state is only available for ModelExchange FMUs.
  • Fmi2Import.Continous — The FMU is in continous state. This state is only available for ModelExchange FMUs.
  • Fmi2Import.StepComplete — The last simulation step was successfully completed. This state is only available for CoSimulation FMUs.
  • Fmi2Import.StepFailed — The last simulation step has failed. This state is only available for CoSimulation FMUs.
  • Fmi2Import.Terminated — The simulation process was terminated.
  • Fmi2Import.Error — A simulation error has occured. The simulation should be either terminated or restored to a prevoiously saved state.
  • Fmi2Import.Fatal — A fatal error has occured within the FMU. The FMU should be abandoned in its current state.

Fmi2Import.type

Read-only property that describes the type of the FMU that was instantiated. The value of this property before the FMU is instantiated is indeterminate. It can be one of:

  • Fmi2Import.TypeME — The FMU was instantiated in ModelExchange mode.
  • Fmi2Import.TypeCS — The FMU was instantiated in CoSimulation mode.

Fmi2Import.time

This read-only property holds the current simulation time of the FMU.

Fmi2Import.typesPlatform

This read-only property holds a string identifier that corresponds to a basic set of primitive types that are used on the current platform by FMI applications. Attempts to use a FMU that was compiled with different typesPlatform than the one used to compile Squish will cause an error, as mandated by the FMI 2.0 standard.

Fmi2Import.types

This read-only property holds an array of Fmi2Type objects that describe type definitions for a FMU.

Fmi2Import.units

This read-only property holds an array of Fmi2Unit objects that describe units used by a FMU.

Fmi2Import.variables

This read-only property holds an array of Fmi2Variable objects that describe variables used by a FMU.

Fmi2Import.vendors

This read-only property holds an array of strings - each describing a software vendor that contributed to the loaded FMU.

Fmi2Import.logCategories

This read-only property holds an array of string identifiers describing log categories that a FMU uses.

Fmi2Import.logCategoriesDescriptions

This read-only property holds an array of string descriptions for log categories that a FMU uses.

Fmi2Import.sourceFilesME

This read-only property holds an array of file names. If a FMU delivers source code for a ModelExchange binary, this array contains the names of those source files.

Fmi2Import.sourceFilesCS

This read-only property holds an array of file names. If a FMU delivers source code for a CoSimulation binary, this array contains the names of those source files.

Fmi2Import.outputs

This read-only property holds a Fmi2VariableArray object that lists output variables defined for a FMU.

Fmi2Import.derivatives

This read-only property holds a Fmi2VariableArray object that lists derivative variables defined for a FMU.

Fmi2Import.discreteStates

This read-only property holds a Fmi2VariableArray object that lists discrete-state variables defined for a FMU.

Fmi2Import initialUnknowns

This read-only property holds a Fmi2VariableArray object that lists variables of initially unknown value defined for a FMU.

Fmi2Import.instantiate(name, type, visible)

This method loads the dynamic library bundled with the FMU and instantiates a FMU object. type must be either Fmi2Import.TypeME or Fmi2Import.TypeCS. The Chosen type must be supported by FMU as indicated by the Fmi2Import.fmuKind property. The default value for this parameter is Fmi2Import.TypeCS if supported by the FMU, and Fmi2Import.TypeME otherwise.

name should be a short string. It is used in error messages as model identifier. Default value for this parameter is the value of the Fmi2Import.name property.

visible should be a boolean value. In case the FMU shows its own GUI, either directly or by an external and possibly pre-existing application. This parameter indicates whether such GUI should be brought to the foreground immediately. If the FMU shows no GUI of any kind, this parameter is ignored.

Note: If any non-static method of a Fmi2Import object is called, this method is called implicitly with default parameter values.

Fmi2Import.setupExperiment(startTime, stopTime, tolerance)

This method informs a FMU to setup the experiment and causes the FMU to enter the initialization mode. This method requires the FMU to be instantiated. If this method is called after the initialization mode has been entered, an error is reported. Default values for parameters are Fmi2Import.defaultExperimentStart, Fmi2Import.defaultExperimentStop and Fmi2Import.defaultExperimentTolerance respectively.

Note: If any method of a Fmi2Import object that requires it to set up is called, this method is called implicitly with default parameter values.

Fmi2Import.exitInitializationMode()

This method causes a FMU to exit initialization mode and enter Fmi2Import.StepComplete (for CoSimulation FMUs) or Fmi2Import.Event (for ModelExchange FMUs) state. This method requires FMU to be in the initialization state.

Note: If any method of a Fmi2Import object that requires it to initialize is called, this method is called implicitly.

Fmi2Import.getCapability(capability)

This method returns an integer that describes the requested capability of a FMU. capablity can be one of:

  • Fmi2Import.ME_needsExecutionTool — If the value of this capability is 1, the FMU doesn't contain the full ModelExchange model implementation and requires additional software to be available.
  • Fmi2Import.ME_canBeInstantiatedOnlyOncePerProcess — If the value of this capability is 1, the FMU can only be instantiated once in ModelExchange mode. This has only informational value, as Squish allows only a single instance of any FMU.
  • Fmi2Import.ME_canGetAndSetFMUstate — If the value of this capability is 1, the ModelExchange FMU can use Fmi2State Fmi2Import.getState() and Fmi2Import.setState(state) to save and restore the current FMU state.
  • Fmi2Import.ME_canSerializeFMUstate — If the value of this capability is 1, the ModelExchange FMU state can be serialized.
  • Fmi2Import.CS_needsExecutionTool — If the value of this capability is 1, the FMU doesn't contain the full CoSimulation model implementation and requires additional software to be available.
  • Fmi2Import.CS_canHandleVariableCommunicationStepSize — If the value of this capability is 0, using different step size values with a CoSimulation FMU may cause an error.
  • Fmi2Import.CS_canBeInstantiatedOnlyOncePerProcess — If the value of this capability is 1, the FMU can only be instantiated once in CoSimulation mode. This has only informational value, as Squish allows only a single instance of any FMU.
  • Fmi2Import.CS_canGetAndSetFMUstate — If the value of this capability is 1, the CoSimulation FMU can utilize Fmi2State Fmi2Import.getState() and Fmi2Import.setState(state) to save and restore the current FMU state.
  • Fmi2Import.CS_canSerializeFMUstate — If the value of this capability is 1, the CoSimulation FMU state can be serialized.

Fmi2Import.getAliasBase(var)

If var is an alias variable, it returns the non-alias variable that var aliases. If var is a non-alias variable, it returns var.

Fmi2Import.getAliases(var)

This method returns a Fmi2VariableArray object that contains all known aliases for the var variable. The array includes the base (non-alias) variable.

Fmi2Import.getVariable(name)

This method returns a Fmi2Variable object that describes a variable of a given name. If no variable named name is found in a FMU, an error is reported.

Fmi2Import.getVariables(names)

This method returns a Fmi2VariableArray object that contains variables of the names in names array. If any of the names in the names array is not found in a FMU, an error is reported.

Fmi2Import.getVariableByName(name)

This method returns a Fmi2Variable object that describes a variable of a given name. If no variable named name is found in a FMU, it returns null.

Fmi2Import.getVariableByReference(vref)

This method returns a Fmi2Variable object that describes a variable of a given vref variable reference. If no variable with vref variable reference is found in a FMU, it returns null.

Fmi2Import.setDebugLogging(loggingOn, categories)

This method sets debug logging on a FMU. If loggingOn is true, logging is enabled. categories is an array that specifies which log categories are to be logged. Entries of this array can be any of the identifiers found in Fmi2Import.logCategories array.

Fmi2Import.setReal(variables, values)

This method sets the values of the FMU variables to the specified values. It returns true in case of success, or false in case the values were rejected by FMU. This usually happens for numerical reasons: value outside bounds was set, integrator could not converge, etc.

variables should be a Fmi2VariableArray object or an array of either variable names or Fmi2Variable class objects. The specified variables must be exclusively real variables.

values should be an array of numeric values for corresponding variables. The length of variables and values must be the same. This method requires the FMU to be instantiated.

Fmi2Import.setInteger(variables, values)

This method sets the values of the FMU variables to the specified values. It returns true in case of success, or false in case the values were rejected by FMU. This usually happens for numerical reasons: value outside bounds was set, integrator could not converge, etc.

variables should be a Fmi2VariableArray object or an array of either variable names or Fmi2Variable class objects. The specified variables must be either integer or enumeration variables.

values should be an array of numeric values for the corresponding variables. The length of variables and values must be the same. This method requires the FMU to be instantiated.

Fmi2Import.setBoolean(variables, values)

This method sets the values of the FMU variables to the specified values. It returns true in case of success, or false in case the values were rejected by FMU. This usually happens for numerical reasons: value outside bounds was set, integrator could not converge, etc.

variables should be a Fmi2VariableArray object or an array of either variable names or Fmi2Variable class objects. The specified variables must be exclusively boolean variables.

values should be an array of boolean values for corresponding variables. The length of variables and values must be the same. This method requires the FMU to be instantiated.

Fmi2Import.setString(variables, values)

This method sets the values of the FMU variables to the specified values. It returns true in case of success, or false in case the values were rejected by FMU. This usually happens for numerical reasons: value outside bounds was set, integrator could not converge, etc.

variables should be a Fmi2VariableArray object or an array of either variable names or Fmi2Variable class objects. The specified variables must be exclusively string variables.

values should be an array of string values for corresponding variables. The length of variables and values must be the same. This method requires the FMU to be instantiated.

Fmi2Import.setValue(variables, values)

This method sets the values of the FMU variables to the specified values. It returns true in case of success, or false in case the values were rejected by FMU. This usually happens for numerical reasons: value outside bounds was set, integrator could not converge, etc.

variables should be a Fmi2VariableArray object or an array of either variable names or Fmi2Variable class objects. The specified variables can be of any type. values should be an array of values for corresponding variables. The length of variables and values must be the same, and the types of values must match corresponding variable definition. This method requires the FMU to be instantiated.

Fmi2Import.getReal(variables)

This method returns an array containing the values of specified FMU variables. variables should be an array of variable names, an array of Fmi2Variable class objects or a Fmi2VariableArray object. The specified variables must be exclusively real variables. This method requires the FMU to be set up.

Fmi2Import.getInteger(variables)

This method returns an array containing the values of specified FMU variables. variables should be an array of variable names, an array of Fmi2Variable class objects or a Fmi2VariableArray object. The specified variables must be either integer or enumeration variables. This method requires the FMU to be set up.

Fmi2Import.getBoolean(variables)

This method returns an array containing the values of specified FMU variables. variables should be an array of variable names, an array of Fmi2Variable class objects or a Fmi2VariableArray object. The specified variables must be exclusively boolean variables. This method requires the FMU to be set up.

Fmi2Import.getString(variables)

This method returns an array containing the values of specified FMU variables. variables should be an array of variable names, an array of Fmi2Variable class objects or a Fmi2VariableArray object. The specified variables must be exclusively string variables. This method requires the FMU to be set up.

Fmi2State Fmi2Import.getState()

This method returns a Fmi2State object that represents the current FMU state. It can be used as an argument to Fmi2Import.setState(state) to restore an FMU from a previously saved state. This method requires a FMU to be instantiated.

Fmi2Import.setState(state)

This method restores the FMU state to state saved in Fmi2State class object state. This method requires a FMU to be instantiated.

Fmi2Import.terminate()

This method terminates the current simulation and changes the current FMU state to Fmi2Import.Terminated. This method requires a FMU to be initialized, and not to be in Fmi2Import.Error state.

Fmi2Import.reset()

This method restores a FMU to the Fmi2Import.Instantiated state. This method requires a FMU to be instantiated.

Fmi2Import.doStep(stepSize, noPriorState)

This method performs a simulation step in CoSimulation mode. It increases internal FMU simulation time Fmi2Import.time by stepSize. It returns true if a simulation step was performed correctly, or false if a simulation step could not be completed. This usually happens for numerical reasons; i.e., the internal FMU integrator did not converge. Returning to a previously saved state and retrying the simulation step with modified inputs may succeed. This method requires a FMU to be initialized.

An optional parameter noPriorState can be specified, it informs the FMU that it will no longer be restored to a state with time before current FMU time. It can be used by a FMU as hint to flush cache buffers. Default value for this parameter is true.

Fmi2Import.run(runtime, stepSize, timeFactor)

Fmi2Import.run(runtime, stepSize)

This method performs a series of simulation steps of stepSize. The simulation is continued until internal FMU time is increased by runtime or until a simulation step could not be performed, in which case this method returns false. This method requires a FMU to be initialized.

An optional argument timeFactor controls speed at which simulation steps are performed. It provides the relation between the simulation time and the simulation execution time. For example if time factor equals 0.5, two seconds of simulation time should be excuted in one second of execution time. In case of simulation of real systems interacting with external software the timeFactor of 1 is probably most useful. Default value for this parameter is 0 - simulation steps are performed as quickly as the environment and the FMU allows.

Note: Squish cannot execute the simulation quicker than an FMU and execution environment allow. If the simulation runs slower than requested, consider increasing stepSize to reduce FMU interaction frequency.

Fmi2Import.runDetached(stepSize, timeFactor)

Fmi2Import.runDetached(stepSize)

This method performs a series of simulation steps of stepSize just as Fmi2Import.run(runtime, stepSize, timeFactor). The difference is, that this method returns immediateley and performs simulation in background, parallel to further test script execution. Any errors encountered during the simulation are reported by Fmi2Import.sync() method. This method requires a FMU to be initialized.

Fmi2Import.sync()

If FMU runs a detached simulation started by Fmi2Import.runDetached(stepSize, timeFactor) it waits until requested simulation steps are performed and returns false if the simulation was interrupted prematurely. If any errors were encountered during the simulation, an exception is thrown.

Fmi2Variable class

The Fmi2Variable class represents a variable exposed by a FMU.

Fmi2Variable.name

This read-only property holds a variable name.

Fmi2Variable.value

This property holds the current value of the variable. If a FMU is not ready to provide variable values (i.e., it wasn't fully initialized), the result is the default empty value - zero for numeric and enumeration types, false for boolean variables and an empty string for string variables.

This property is read-only. to change values of input variables use Fmi2Import.setValue(variables, values) or type-specific Fmi2Import.set* methods.

Fmi2Variable.description

This read-only property holds a human-readable variable description.

Fmi2Variable.valueReference

This read-only property holds the value reference for a variable. Value reference is an integer that is used internally by an FMU to identify the variable. Alias variables use the same valueReference as their base variable, and therefore always have the same value.

Fmi2Variable.declaredType

This read-only property holds an object of the Fmi2Type class type in case the variable has a declared type, null otherwise.

Fmi2Variable.baseType

This read-only property holds a value that describes the basic data type of a variable. It can be one of:

  • Fmi2Import.Real — a real variable
  • Fmi2Import.Integer — an integer variable
  • Fmi2Import.Boolean — a boolean variable
  • Fmi2Import.String — a string variable
  • Fmi2Import.Enum — an enumeration variable

Fmi2Variable.hasStart

This read-only property holds a boolean that indicates whether a variable has a defined startup value.

Fmi2Variable.variability

This read-only property holds a value that describes when changes in value of a variable are allowed. It can be one of:

  • Fmi2Variable.Constant — the value of a variable never changes
  • Fmi2Variable.Fixed — the value of a variable remains constant after a FMU has been initialized
  • Fmi2Variable.Tunable — The value cannot change between events (ModelExchange) or between simulation steps (CoSimulation)
  • Fmi2Variable.Discrete — The value cannot change between events (ModelExchange) or between simulation steps (CoSimulation)
  • Fmi2Variable.Continuous — no restrictions on value changes
  • Fmi2Variable.UnknownVariability — unknown variablity

Fmi2Variable.causality

This read-only property indicates how the value for a variable is obtained. It can be one of:

  • Fmi2Variable.Parameter — an independent parameter; can be set by a test script.
  • Fmi2Variable.CalculatedParameter — calculated within the FMU model during initialization or after a parameter is changed.
  • Fmi2Variable.Input — an input variable; can be set by a test script.
  • Fmi2Variable.Output — an output variable;
  • Fmi2Variable.Local — internal FMU variable;
  • Fmi2Variable.Independent — an independent variable for a simulation. All other variables are defined as functions of the independent variable. Default independent variable is 'time'. There can be at most one independent variable in a FMU;
  • Fmi2Variable.UnknownCausaility — unknown causality.

Fmi2Variable.initial

This read-only property holds a value that indicates how the initial value for a variable is obtained. It can be one of:

  • Fmi2Variable.Exact — a start attribute is used as initial value;
  • Fmi2Variable.Approx — an initial value is computed iteratively. A start attribute is used as initial value for computation;
  • Fmi2Variable.Calculated — an initial value is calculated from values of other variables during initialization.

Fmi2Variable.previous

This read-only property holds a Fmi2Variable that holds the previous value of the variable, or null if no such variable was defined.

Fmi2Variable.isAlias

This read-only property holds a boolean that is true if the variable is an alias for another variable.

Fmi2RealVariable Fmi2Variable.asReal()

This method casts a variable to Fmi2RealVariable object if its baseType is Real, or null otherwise.

Fmi2IntegerVariable Fmi2Variable.asInteger()

This method casts a variable to Fmi2IntegerVariable object if its baseType is Integer, or null otherwise.

Fmi2EnumVariable Fmi2Variable.asEnum()

This method casts a variable to Fmi2EnumVariable object if its baseType is Enum, or null otherwise.

Fmi2StringVariable Fmi2Variable.asString()

This method casts a variable to Fmi2StringVariable object if its baseType is String, or null otherwise.

Fmi2BooleanVariable Fmi2Variable.asBoolean()

This method casts a variable to Fmi2BooleanVariable object if its baseType is Boolean, or null otherwise.

Fmi2RealVariable.start

Fmi2IntegerVariable.start

Fmi2EnumVariable.start

Fmi2StringVariable.start

Fmi2BooleanVariable.start

These read-only properties hold start values of appropriate type for a variable.

Fmi2RealVariable.min

Fmi2RealVariable.max

Fmi2IntegerVariable.min

Fmi2IntegerVariable.max

Fmi2EnumVariable.min

Fmi2EnumVariable.max

These read-only properties hold minmal and maximal values for a variable.

Fmi2RealVariable.derivativeOf

This read-only property holds an Fmi2RealVariable object for which the variable is a derivative, or null if none.

Fmi2RealVariable.unit

This read-only property holds an Fmi2Unit object if defined for a variable or null otherwise.

Fmi2RealVariable.displayUnit

This read-only property holds an Fmi2DisplayUnit object if defined for a variable or null otherwise.

Fmi2Type class

The Fmi2Type class contains information about an FMI type definition. It serves purely informational role.

Fmi2Type.name

This read-only property holds a name for the type definition.

Fmi2Type.description

This read-only property holds a description for the type definition.

Fmi2Type.baseType

This read-only property holds a base type for the type definition. The meaning of this value is the same as Fmi2Variable.baseType.

Fmi2Type.quantity

This read-only property holds a string that describes quantity of the type definition.

Fmi2RealType Fmi2Type.asReal()

This method casts a type definition to the Fmi2RealType object if its baseType is Real, or null otherwise.

Fmi2IntegerType Fmi2Type.asInteger()

This method casts a type definition to the Fmi2ItegerType object if its baseType is Real, or null otherwise.

Fmi2EnumType Fmi2Type.asEnum()

This method casts a type definition to the Fmi2EnumType object if its baseType is Enum, or null otherwise.

Fmi2Unit class

The Fmi2Unit class contains information about an FMI unit definition. Each Fmi2Unit class can have a number of associated Fmi2DisplayUnit objects. Display units are used to display values in a user-friendly format. Both classes serve purely informational role.

Fmi2Unit.name

This read-only property holds a name for the unit definition.

Fmi2Unit.displayUnits

This read-only property holds an array of Fmi2DisplayUnit objects that correspond to the unit definition.

Fmi2Unit.SIexponents

This read-only property holds an array of integers that describe SI exponents for the unit definition.

Fmi2Unit.SIfactor

Fmi2Unit.SIoffset

These read-only properties hold a factor and an offset to a corresponding SI unit.

Fmi2Unit.fromSI(value)

This method converts a value expressed in a corresponding SI unit to a value in the specified unit.

Fmi2Unit.toSI(value)

This method converts a value expressed in the specified unit to a value in a corresponding SI unit.

Fmi2DisplayUnit.name

This read-only property holds a name for the display unit definition.

Fmi2DisplayUnit.baseUnit

This read-only property holds an associated Fmi2Unit object.

Fmi2DisplayUnit.factor

Fmi2DisplayUnit.offset

These read-only properties hold a factor and an offset to a corresponding Fmi2Unit.

Fmi2DisplayUnit.fromDisplayUnit(value)

This method converts a value expressed in a corresponding Fmi2Unit to a value in the display unit.

Fmi2DisplayUnit.toDisplayUnit(value)

This method converts a value expressed in the display unit to a value in a corresponding Fmi2Unit unit.

Fmi2State class

Some FMUs have the ability to store their current state and to restore from a previously saved state. Fmi2State represents a stored FMU state.

You can query ability to save and restore the state of an FMU using Fmi2Import.getCapability(capability) method with the Fmi2Import.CS_canGetAndSetFMUstate flag. Additionally, FMUs with the Fmi2Import.CS_canSerializeFMUstate capability flag set can serialize such a state into a sequence of bytes that can be transfered between FMU instances.

Fmi2DisplayUnit.size

This read-only property holds a size of a byte array that can hold serialized state data.

Fmi2State.serialize()

This method serializes the represented state and returns it as an array of bytes.

Examples

Running a simulation

The following snippet shows an example of loading a FMU object, accessing its variables and running the simulation process.

function main() {
    startFMI();
    var fmu = Fmi2Import.create( '/data/deviceModel.fmu' );

    // Retrieves model variable called 'varX'
    var variableX = fmu.getVariable( "varX" );

    // An alternative approach
    var variableY = findObject( "{type='Fmi2Variable' name='varY'}" );

    // Set the values of the variables
    fmu.setValue( [ variableX, variableY, "varZ" ], [ 1, 2, 4 ] );

    // Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 );

    // Run the simulation for specific time
    snooze(5);

    // Compare the value of a variable with expected value
    test.compare( variableX.value, 1 );

    // Destroys the FMI object and terminates 'fmiutil'
    fmu.destroy();
}
sub main() {
    startFMI();
    my $fmu = Fmi2Import::create( '/data/deviceModel.fmu' );

    # Retrieves model variable called 'varX'
    my $variableX = $fmu->getVariable( "varX" );

    # An alternative approach
    my $variableY = findObject( "{name='varY' type='Fmi2Variable'}" );

    # Set the values of the variables
    @variables = ( "varX", "varY", "varZ" );
    @values = ( 1, 2, 4 );
    $fmu->setValue( \@variables, \@values );

    # Run the simulation in the background at real-time pace.
    $fmu->runDetached( 0.01, 1 );

    # Run the simulation for specific time
    snooze(5);

    # Compare the value of a variable with expected value
    test::compare( $variableX->value, 1 );

    # Destroys the FMI object and terminates 'fmiutil'
    $fmu->destroy();
}
def main():
    startFMI()
    fmu = Fmi2Import.create( '/data/deviceModel.fmu' )

    # Retrieves model variable called 'varX'
    variableX = fmu.getVariable( "varX" )

    # An alternative approach
    variableY = findObject( "{name='varY' type='Fmi2Variable'}" )

    # Set the values of the variables
    fmu.setValue( [ variableX, variableY, "varZ" ], [ 1, 2, 4 ] )

    # Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 )

    # Run the simulation for specific time
    snooze(5)

    # Compare the value of a variable with expected value
    test.compare( variableX.value, 1 )

    # Destroys the FMI object and terminates 'fmiutil'
    fmu.destroy()
require 'squish'

include Squish

def main
    startFMI()
    fmu = Fmi2Import.create( '/data/deviceModel.fmu' )

    # Retrieves model variable called 'varX'
    variableX = fmu.getVariable( "varX" )

    # An alternative approach
    variableY = findObject( "{name='varY' type='Fmi2Variable'}" )

    # Set the values of the variables
    fmu.setValue( [ "varX", "varY", "varZ" ], [ 1, 2, 4 ] )

    # Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 )

    # Run the simulation for specific time
    snooze(5)

    # Compare the value of a variable with expected value
    Test.compare( variableX.value, 1 )

    # Destroys the FMI object and terminates 'fmiutil'
    fmu.destroy()
end
proc main {} {
    startFMI
    set fmu [ invoke Fmi2Import create "/data/deviceModel.fmu" ]

    # Retrieves model variable called 'varX'
    set variableX [ invoke $fmu getVariable  "varX" ];

    # An alternative approach
    set variableY [ findObject "{name='varY' type='Fmi2Variable'}" ]

    # Set the values of the variables
    property set $variableX value 1
    property set $variableY value 2
    property set [ findObject "{name='varZ' type='Fmi2Variable'}" ] value 4

    # Run the simulation in the background at real-time pace.
    invoke $fmu runDetached 0.01 1

    # Run the simulation for specific time
    snooze 5

    # Compare the value of a variable with expected value
    test compare [ property get $variableX value ] 1

    # Destroys the FMI object and terminates 'fmiutil'
    invoke $fmu destroy
}

Running a simulation in parallel to the AUT

An FMU object is created in the utility process. If the test script accesses FMU and AUT, the current context must be changed to match currently accessed object, as described in How to Start and Access Multiple Applications Under Test.

function main() {
    var fmictx = startFMI();
    var fmu = Fmi2Import.create( '/data/deviceModel.fmu' );

    // Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 );

    var autctx = startApplication( "/an/aut" );
    activateItem( waitForObjectItem( ":_QMenuBar", "Device" ) );
    activateItem( waitForObjectItem( ":Device_QMenu", "Start" ) );
    setApplicationContext( fmictx );
    test.compare( fmu.getVariable( "isStarted" ).value, True );

    fmu.setValue( [ "isRunning" ], [ 1 ] );
    setApplicationContext( autctx );
    test.compare( waitForObject( ":Status_QLabel" ).text, "Running" );

    setApplicationContext( fmictx );
    fmu.destroy();
}
sub main() {
    my $fmictx = startFMI();
    my $fmu = Fmi2Import::create( '/data/deviceModel.fmu' );

    # Run the simulation in the background at real-time pace.
    $fmu->runDetached( 0.01, 1 );

    my $autctx = startApplication( "/an/aut" );
    activateItem( waitForObjectItem( ":_QMenuBar", "Device" ) );
    activateItem( waitForObjectItem( ":Device_QMenu", "Start" ) );
    setApplicationContext( $fmictx );
    test::compare( $fmu->getVariable( "isStarted" )->value, True );

    @variables = ( "isRunning" );
    @values = ( 1 );
    $fmu->setValue( \@variables, \@values );
    setApplicationContext( $autctx );
    test::compare( waitForObject( ":Status_QLabel" )->text, "Running" );

    setApplicationContext( $fmictx );
    $fmu.destroy();
}
def main():
    fmictx = startFMI()
    fmu = Fmi2Import.create( '/data/deviceModel.fmu' )

    // Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 )

    autctx = startApplication( "/an/aut" )
    activateItem( waitForObjectItem( ":_QMenuBar", "Device" ) )
    activateItem( waitForObjectItem( ":Device_QMenu", "Start" ) )
    setApplicationContext( fmictx )
    test.compare( fmu.getVariable( "isStarted" ).value, 1 )

    fmu.setValue( [ "isRunning" ], [ 1 ] )
    setApplicationContext( autctx )
    test.compare( waitForObject( ":Status_QLabel" ).text, "Running" )

    setApplicationContext( fmictx )
    fmu.destroy()
require 'squish'

include Squish

def main() {
    fmictx = startApplication( "fmiutil" )
    fmu = Fmi2Import.create( '/data/deviceModel.fmu' )

    # Run the simulation in the background at real-time pace.
    fmu.runDetached( 0.01, 1 )

    var autctx = startApplication( "/an/aut" )
    activateItem( waitForObjectItem( ":_QMenuBar", "Device" ) )
    activateItem( waitForObjectItem( ":Device_QMenu", "Start" ) )
    setApplicationContext( fmictx )
    test.compare( fmu.getVariable( "isStarted" ).value, True )

    fmu.setValue( [ "isRunning" ], [ 1 ] )
    setApplicationContext( autctx )
    test.compare( waitForObject( ":Status_QLabel" ).text, "Running" )

    setApplicationContext( fmictx )
    fmu.destroy()
}
proc main {} {
    set fmictx [ startFMI ]
    set fmu [ invoke Fmi2Import create "/data/deviceModel.fmu" ]

    # Run the simulation in the background at real-time pace.
    invoke $fmu runDetached 0.01 1

    set autctx [ startApplication  "/an/aut" ]
    invoke activateItem [waitForObjectItem ":_QMenuBar" "Device" ]
    invoke activateItem [waitForObjectItem ":Device_QMenu" "Start" ]
    setApplicationContext $fmictx
    test compare [ property get [ invoke $fmu getVariable "isStarted" ] value ] 1

    set isRunning [ invoke $fmu getVariable  "isRunning" ];
    property set $isRunning value 1
    setApplicationContext $autctx
    test compare [ property get [ waitForObject ":Status_QLabel" ] text ] "Running"

    setApplicationContext $fmictx
    invoke $fmu destroy

Waiting for simulation results

To wait for a simulation variable to take a specific value, use Object waitForObject(objectOrName). If the value property is specified, it will find only the variable of specified value, and wait if no such variable exists.

// will wait until variable 'varY' has a value of 1.
var variableY = waitForObject( "{type='Fmi2Variable' name='varY' value='1'}" );
// will wait until variable 'varY' has a value of 1.
my $variableY = waitForObject( "{type='Fmi2Variable' name='varY' value='1'}" );
// will wait until variable 'varY' has a value of 1.
variableY = waitForObject( "{type='Fmi2Variable' name='varY' value='1'}" )
// will wait until variable 'varY' has a value of 1.
variableY = waitForObject( "{type='Fmi2Variable' name='varY' value='1'}" );
// will wait until variable 'varY' has a value of 1.
set variableY [ waitForObject  "{type='Fmi2Variable' name='varY' value='1'}" ]

If the condition to wait for is more complex, a Boolean waitFor(condition) function can be used.

var variableY = findObject( "{type='Fmi2Variable' name='varY'}" );
waitFor( function() {
    return variableY.value < 1;
} );
my $variableY = findObject( "{type='Fmi2Variable' name='varY'}" );
waitFor( function() {
    return $variableY->value < 1;
} );
variableY = findObject( "{type='Fmi2Variable' name='varY'}" )
waitFor( lambda: variableY.value < 1 )
var variableY = findObject( "{type='Fmi2Variable' name='varY'}" )
waitFor( lambda { return variableY.value < 1 } )
set variableY [ findObject "{type='Fmi2Variable' name='varY'}" ]
waitFor [ proc "" {} { expr [ property get $variableY value ] < 1 } ]

In case a variable of interest has the expected value for a relatively short period of time, it is possible - due to parallel nature of test script execution - that the above functions miss that value entirely. To gain fine control over the simulation process, run the variable directly from the test script.

setApplicationContext( fmictx );
// Stops background execution of the simulation process (if started).
fmu.sync();

var variableY = findObject( "{type='Fmi2Variable' name='varY'}" );
for ( var i=0; i<1000; ++i ) {
    fmu.doStep( 0.01 );
    if ( variableY.value < 1 )
        break;
}
test.verify( variableY.value < 1 );
// Re-start detahed execution ( if required )
fmu.runDetached( 0.01, 1 );
setApplicationContext( $fmictx );
// Stops background execution of the simulation process (if started).
$fmu->sync();

my $variableY = findObject( "{type='Fmi2Variable' name='varY'}" );
for ( my $i=0; $i<1000; $i++ ) {
    $fmu->doStep( 0.01 );
    if ( $variableY->value < 1 ) {
        last;
    }
}
test::verify( $variableY->value < 1 );
// Re-start detahed execution ( if required )
$fmu->runDetached( 0.01, 1 );
setApplicationContext( fmictx )
// Stops background execution of the simulation process (if started).
fmu.sync()

variableY = findObject( "{type='Fmi2Variable' name='varY'}" )
for x in range(0, 1000):
    fmu.doStep( 0.01 )
    if variableY.value < 1:
        break

test.verify( variableY.value < 1 )
// Re-start detahed execution ( if required )
fmu.runDetached( 0.01, 1 )
setApplicationContext( fmictx )
// Stops background execution of the simulation process (if started).
fmu.sync()

variableY = findObject( "{type='Fmi2Variable' name='varY'}" )
for x in 1..1000:
    fmu.doStep( 0.01 )
    if variableY.value < 1 then
        break
    end
end

test.verify( variableY.value < 1 )
// Re-start detahed execution ( if required )
fmu.runDetached( 0.01, 1 )
setApplicationContext $fmictx
# Stops background execution of the simulation process (if started).
invoke fmu sync

set variableY [ findObject "{type='Fmi2Variable' name='varY'}" ]
for {set i 0} {$i < 1000} {incr i} {
    invoke $fmu doStep 0.01
    if { expr [ property get $variableY value ] < 1 } {
        break
    }
}
invoke test verify [ expr [ property get $variableY value ] < 1 ]
# Re-start detached execution ( if required )
invoke fmu runDetached 0.01 1

© 2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners.
The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.