Table of Contents
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 (ie. 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.
![]() | 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. In order 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. In order to launch fmiutil
, the
startFMI
function can be used.
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 Squish IDE'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 (Section 8.3.22).
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.
The Fmi2Import
class is the core of the Squish FMI
Interface support. It represents an FMU imported by Squish.
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.
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.
These read-only properties hold meatadata for a FMU object as specified by FMI 2.0 standard.
Fmi2Import.fmuKindThis 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
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.
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.
This read-only property holds the current simulation time of the FMU.
Fmi2Import.typesPlatformThis 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.typesThis 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.
This read-only property holds an array of Fmi2Variable
objects that describe variables used by a FMU.
This read-only property holds an array of strings - each describing a software vendor that contributed to the loaded FMU.
Fmi2Import.logCategoriesThis read-only property holds an array of string identifiers describing log categories that a FMU uses.
Fmi2Import.logCategoriesDescriptionsThis read-only property holds an array of string descriptions for log categories that a FMU uses.
Fmi2Import.sourceFilesMEThis 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.sourceFilesCSThis 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.
This read-only property holds a Fmi2VariableArray
object
that lists derivative variables defined for a FMU.
This read-only property holds a Fmi2VariableArray
object
that lists discrete-state variables defined for a FMU.
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 |
---|---|
In case any non-static method of a |
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 |
---|---|
In case any method of a |
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 |
---|---|
In case any method of a |
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 utilize
Fmi2Import.getState
and
Fmi2Import.setState
in order 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
Fmi2Import.getState
and
Fmi2Import.setState
in order 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 (Section 6.20.3) 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 (Section 6.20.3) objects. The
specified variables must be either integer or enumeration 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.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 (Section 6.20.3) 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 (Section 6.20.3) 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.
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 (Section 6.20.3) 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 (Section 6.20.3) 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 (Section 6.20.3) 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 (Section 6.20.3) 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 (Section 6.20.3) objects or a
Fmi2VariableArray
object. The
specified variables must be exclusively string variables. This method requires
the FMU to be set-up.
This method returns a Fmi2State
object that represents the current FMU state. It
can be used as an argument to Fmi2Import.setState
to restore
an FMU from a previously saved state. This method requires a FMU to be
instantiated.
This method restores the FMU state to state saved in
Fmi2State class (Section 6.20.6) 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; ie. 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)
;
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)
;
This method performs a series of simulation steps of stepSize
just
as Fmi2Import.run
. 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.
If FMU runs a detached simulation started by
Fmi2Import.runDetached
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.
The Fmi2Variable
class represents a variable exposed by a FMU.
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. In order to change values of input variables use
Fmi2Import.setValue
or type-specific
Fmi2Import.set*
methods.
This read-only property holds a human-readable variable description.
Fmi2Variable.valueReferenceThis 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 (Section 6.20.4)
type in case the variable has a declared type, null
otherwise.
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.
This read-only property holds a boolean that indicates whether a variable has a defined startup value.
Fmi2Variable.variabilityThis 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.
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.
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.
This read-only property holds a Fmi2Variable
that holds
the previous value of the variable, or null
if no such variable was defined.
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.
These read-only properties hold start values of appropriate type for a variable.
Fmi2RealVariable.minFmi2RealVariable.maxFmi2IntegerVariable.minFmi2IntegerVariable.maxFmi2EnumVariable.minFmi2EnumVariable.maxThese 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.
This read-only property holds an Fmi2Unit
object if defined for a variable or
null
otherwise.
This read-only property holds an Fmi2DisplayUnit
object
if defined for a variable or null
otherwise.
The Fmi2Type
class contains information about an FMI type
definition. It serves purely informational role.
This read-only property holds a name for the type definition.
Fmi2Type.descriptionThis read-only property holds a description for the type definition.
Fmi2Type.baseTypeThis read-only property holds a base type for the type definition. The meaning of this value is the same as Fmi2Variable.baseType.
Fmi2Type.quantityThis 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.
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.
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.
This read-only property holds an array of integers that describe SI exponents for the unit definition.
Fmi2Unit.SIfactorFmi2Unit.SIoffsetThese 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.nameThis read-only property holds a name for the display unit definition.
Fmi2DisplayUnit.baseUnit
This read-only property holds an associated Fmi2Unit
object.
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.
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
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.
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.
Table of Contents
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 }
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 (Section 5.12.1).
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
In order to wait for a simulation variable to take a specific value,
waitForObject
can be used. 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
waitFor
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. In order to gain fine control over the simulation process, it can be run 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