FMI接口支持

与外部设备通信的应用程序在单独测试时本质上是困难的。存在大量的仿真工具,这些工具允许这样的应用程序与模拟设备进行接口连接。这使得在缺少实际设备的情况下进行应用开发、测试和评估成为可能。此外,仿真可以轻松地提供有关当前设备状态的信息,并模拟在物理设备上难以实现的条件(例如,特定的故障)。Squish支持使用FMI接口与这些工具进行通信。

功能性模拟接口(Functional Mockup Interface,简称FMI)是动态模型交换和协同仿真的行业标准。它介绍了功能性模拟单元(Functional Mockup Units,简称FMUs)的导出器和导入器之间的接口。Squish具有导入支持FMI 2.0协同仿真模式的FMU的能力。作为FMU导入器,Squish可以访问FMU暴露的所有变量,并负责驱动仿真过程。以下部分介绍了Squish提供的用于导入和执行FMUs的API。

完整的FMI 2.0规范文本可以在以下网址获得:https://www.fmi-standard.org。Squish对FMI接口的支持基于JModelica平台上的FMI库

FMI概述

注意:此处描述的接口不是最终版本。描述的API的细节可能会在功能的发布版本中发生变化。

FMI标准指定FMU可以包含编译后的可执行代码,以平台特定的共享对象文件的形式,或者是一组可以被FMI导入器编译的源代码文件。Squish只支持前者。

不建议将FMU加载到与AUT相同的上下文中。为了将FMU与其他任何进程分开,Squish提供了一个实用程序可执行文件fmiutil。FMI功能仅在fmiutil工具的应用程序上下文中可用。它位于Squish二进制安装目录中。要启动fmiutil,请使用ApplicationContext startFMI()函数。

ApplicationContext startFMI

ApplicationContext startFMI(host)

ApplicationContext startFMI(host, port)

ApplicationContext startFMI(host, port, timeoutSecs)

启动一个新的fmiutil实例并返回其应用程序上下文的句柄。

可选地,作为第一个和第二个参数可以指定hostport。如果使用这些参数,将连接到指定的主机和端口上监听的squishserver(而不是连接到在squishide的设置中或在squishrunner的命令行中指定的默认主机和端口)。

第三个参数是timeoutSecs(以秒为单位的整数值)。这告诉Squish应在抛出错误之前准备等待应用程序启动多长时间。如果指定,此值将覆盖squishrunner的默认AUT超时。如果没有指定,将使用squishserver的默认值——这是20秒,除非已更改。请参阅Squish服务器设置对话框

如果您想指定超时,但又不想更改主机或端口,可以通过传递空字符串作为主机(这将使Squish使用配置的主机—默认为localhost)和传递-1作为端口来实现。

Fmi2Import类

Fmi2Import类是Squish FMI接口支持的核心。它表示由Squish导入的FMU。

Fmi2Import Fmi2Import.create(filename, workingDirectory)

Fmi2Import Fmi2Import.create(filename)

此静态方法使用指定的目录作为工作目录打开指定的FMU,并返回一个 Fmi2Import 对象。如果未指定 workingDirectory,则在每个方法调用时在 %TEMP% 目录中创建一个临时目录。

Fmi2Import.lastError

该只读属性包含描述FMU遇到的上一个错误的字符串。当 Fmi2Import 方法返回错误时将其设置。

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

这些只读属性包含根据FMI 2.0标准指定的FMU对象元数据。

Fmi2Import.fmuKind

该只读属性包含表示FMU支持的FMI模式值的值。它可以是一下之一

  • Fmi2Import.KindUnknown — 未知FMU类型
  • Fmi2Import.KindME — 仅支持模型交换模式的FMU
  • Fmi2Import.KindCS — 仅支持协同仿真的FMU
  • Fmi2Import.KindMECS — 支持模型交换和协同仿真模式的FMU

Fmi2Import.state

该只读属性包含FMU的当前状态。可以是一下之一

  • Fmi2Import.Preloaded — 解析了描述FMU的XML文件,但尚未加载二进制模型可执行文件。
  • Fmi2Import.Instantiated — 成功加载二进制模型可执行文件并实例化了模型。
  • Fmi2Import.Init — FMU已进入初始化模式。
  • Fmi2Import.Event — FMU处于事件状态。此状态仅适用于模型交换FMU。
  • Fmi2Import.Continous — FMU处于连续状态。此状态仅适用于模型交换FMU。
  • Fmi2Import.StepComplete — 上一个仿真步骤成功完成。此状态仅适用于协同仿真FMU。
  • Fmi2Import.StepFailed — 上一个仿真步骤失败。此状态仅适用于协同仿真FMU。
  • Fmi2Import.Terminated — 仿真过程已被终止。
  • Fmi2Import.Error — 发生仿真错误。仿真应被终止或恢复到之前保存的状态。
  • Fmi2Import.Fatal — FMU内部发生致命错误。应放弃当前状态的FMU。

Fmi2Import.type

只读属性,描述已实例化的FMU的类型。在FMU实例化之前此属性的值是不确定的。它可以是以下之一

  • Fmi2Import.TypeME — FMU在模型交换模式中实例化。
  • Fmi2Import.TypeCS — FMU在协同仿真模式中实例化。

Fmi2Import.time

此只读属性包含FMU的当前仿真时间。

Fmi2Import.typesPlatform

此只读属性包含一个字符串标识符,对应于在当前平台上FMI应用程序使用的基原始数据类型集合。如果尝试使用使用与Squish编译不同的typesPlatform编译的FMU,将引起错误,这是FMI 2.0标准的强制要求。

Fmi2Import.types

此只读属性包含一个Fmi2Type对象数组,用于描述FMU的类型定义。

Fmi2Import.units

此只读属性包含一个Fmi2Unit对象数组,用于描述FMU使用的单位。

Fmi2Import.variables

此只读属性包含一个Fmi2Variable对象数组,用于描述FMU使用的变量。

Fmi2Import.vendors

此只读属性包含一个字符串数组,每个字符串描述了一个为加载的FMU做出贡献的软件供应商。

Fmi2Import.logCategories

此只读属性包含一个字符串标识符数组,描述了FMU使用的日志分类。

Fmi2Import.logCategoriesDescriptions

此只读属性包含一个字符串描述数组,描述了FMU使用的日志分类。

Fmi2Import.sourceFilesME

此只读属性包含一个文件名数组。如果FMU为模型交换二进制文件提供源代码,则此数组包含那些源文件的名称。

Fmi2Import.sourceFilesCS

此只读属性包含一个文件名数组。如果FMU为协同仿真二进制文件提供源代码,则此数组包含那些源文件的名称。

Fmi2Import.outputs

此只读属性包含一个Fmi2VariableArray对象,列出了为FMU定义的输出变量。

Fmi2Import.derivatives

此只读属性包含一个Fmi2VariableArray对象,列出了为FMU定义的导数变量。

Fmi2Import.discreteStates

此只读属性包含一个Fmi2VariableArray对象,列出了为FMU定义的离散状态变量。

Fmi2Import初始未知值

这个只读属性包含一个 Fmi2VariableArray 对象,该对象列出了为FMU定义的初始未知值的变量。

Fmi2Import.instantiate(name, type, visible)

此方法加载与FMU捆绑的动态库并实例化一个FMU对象。type 必须是 Fmi2Import.TypeMEFmi2Import.TypeCS。选择类型必须由 Fmi2Import.fmuKind 属性指示的支持 FMU 支持。如果 FMU 支持,则此参数的默认值为 Fmi2Import.TypeCS,否则为 Fmi2Import.TypeME

name 应该是一个短字符串。它用于错误信息中的模型标识符。此参数的默认值为 Fmi2Import.name 属性的值。

visible 应该是一个布尔值。如果 FMU 通过直接或外部和可能已存在的应用程序显示自己的 GUI,则此参数指示是否应立即将此类 GUI 置于前台。如果 FMU 不显示任何类型的 GUI,则忽略此参数。

注意: 如果调用 Fmi2Import 对象的任何非静态方法,则此方法将使用默认参数值隐式调用。

Fmi2Import.setupExperiment(startTime, stopTime, tolerance)

此方法通知 FMU 设置实验并使 FMU 进入初始化模式。此方法要求 FMU 已实例化。如果在已进入初始化模式后调用此方法,则将报告错误。参数的默认值分别为 Fmi2Import.defaultExperimentStartFmi2Import.defaultExperimentStopFmi2Import.defaultExperimentTolerance

注意: 如果调用需要设置的任何 Fmi2Import 对象方法的操作,则此方法将使用默认参数值隐式调用。

Fmi2Import.exitInitializationMode()

此方法使 FMU 离开初始化模式并进入 Fmi2Import.StepComplete(对于协仿真 FMU)或 Fmi2Import.Event(对于模型交换 FMU)状态。此方法要求 FMU 处于初始化状态。

注意: 如果调用需要初始化的任何 Fmi2Import 对象方法的操作,则此方法将隐式调用。

Fmi2Import.getCapability(capability)

此方法返回一个整数,用于描述请求的 FMU capabilitycapablity 可以是以下之一

  • Fmi2Import.ME_needsExecutionTool — 如果此能力的值为 1,则 FMU 不包含完整的模型交换模型实现,并且需要额外的软件可用。
  • Fmi2Import.ME_canBeInstantiatedOnlyOncePerProcess — 如果此能力的值为 1,则 FMU 仅能在模型交换模式下实例化一次。这只有信息价值,因为 Squish 只允许任何 FMU 单个实例。
  • Fmi2Import.ME_canGetAndSetFMUstate — 如果此能力的值为 1,则模型交换 FMU 可以使用 Fmi2State Fmi2Import.getState()Fmi2Import.setState(state) 保存和恢复当前 FMU 状态。
  • Fmi2Import.ME_canSerializeFMUstate — 如果此功能的值为1,则ModelExchange FMU状态可以序列化。
  • Fmi2Import.CS_needsExecutionTool — 如果此功能的值为1,则FMU不包含完整的CoSimulation模型实现,需要其他软件可用。
  • Fmi2Import.CS_canHandleVariableCommunicationStepSize — 如果此功能的值为0,使用与CoSimulation FMU不同的步长值可能会引发错误。
  • Fmi2Import.CS_canBeInstantiatedOnlyOncePerProcess — 如果此功能的值为1,该FMU在CoSimulation模式下只能实例化一次。这只有信息价值,因为Squish只允许任何FMU的单个实例。
  • Fmi2Import.CS_canGetAndSetFMUstate — 如果此功能的值为1,CoSimulation FMU可以使用Fmi2State Fmi2Import.getState()Fmi2Import.setState(state)来保存和恢复当前FMU状态。
  • Fmi2Import.CS_canSerializeFMUstate — 如果此功能的值为1,CoSimulation FMU状态可以序列化。

Fmi2Import.getAliasBase(var)

如果var是一个别名变量,则返回var所指定的非别名变量。如果var是非别名变量,则返回var

Fmi2Import.getAliases(var)

此方法返回一个包含var变量的所有已知别名的Fmi2VariableArray对象。数组包括基础(非别名)变量。

Fmi2Import.getVariable(name)

此方法返回一个描述具有给定name的变量的Fmi2Variable对象。如果在FMU中找不到名为name的变量,则报告错误。

Fmi2Import.getVariables(names)

此方法返回一个包含names数组中名称的变量的Fmi2VariableArray对象。如果names数组中的任何名称在FMU中找不到,则报告错误。

Fmi2Import.getVariableByName(name)

此方法返回一个描述具有给定name的变量的Fmi2Variable对象。如果在FMU中找不到名为name的变量,则返回null

Fmi2Import.getVariableByReference(vref)

此方法返回一个描述具有给定vref变量引用的变量的Fmi2Variable对象。如果在FMU中找不到具有vref变量引用的变量,则返回null

Fmi2Import.setDebugLogging(loggingOn, categories)

此方法设置FMU的调试日志。如果loggingOntrue,则启用日志。categories是一个数组,指定要记录的日志类别。此数组的条目可以是Fmi2Import.logCategories数组中找到的任何标识符。

Fmi2Import.setReal(variables, values)

此方法将FMU变量的值设置为指定的值。如果成功,则返回 true,如果值被FMU拒绝,则返回 false。这通常是由于数值原因:设置了超出范围的值,积分器无法收敛等。

variables 应该是一个 Fmi2VariableArray 对象,或者是一个变量名数组或 Fmi2Variable 类 对象的数组。指定的变量必须是实变量。

values 应该是相应变量的数值数组。变量数组和值的数组的长度必须相同。此方法需要已实例化的FMU。

Fmi2Import.setInteger(variables, values)

此方法将FMU变量的值设置为指定的值。如果成功,则返回 true,如果值被FMU拒绝,则返回 false。这通常是由于数值原因:设置了超出范围的值,积分器无法收敛等。

variables 应该是一个 Fmi2VariableArray 对象,或者是一个变量名数组或 Fmi2Variable 类 对象的数组。指定的变量必须是整数或枚举变量。

values 应该是相应变量的数值数组。变量数组和值的数组的长度必须相同。此方法需要已实例化的FMU。

Fmi2Import.setBoolean(variables, values)

此方法将FMU变量的值设置为指定的值。如果成功,则返回 true,如果值被FMU拒绝,则返回 false。这通常是由于数值原因:设置了超出范围的值,积分器无法收敛等。

variables 应该是一个 Fmi2VariableArray 对象,或者是一个变量名数组或 Fmi2Variable 类 对象的数组。指定的变量必须是布尔变量。

values 应该是相应变量的布尔值数组。变量数组和值的数组的长度必须相同。此方法需要已实例化的FMU。

Fmi2Import.setString(variables, values)

此方法将FMU变量的值设置为指定的值。如果成功,则返回 true,如果值被FMU拒绝,则返回 false。这通常是由于数值原因:设置了超出范围的值,积分器无法收敛等。

variables 应该是一个 Fmi2VariableArray 对象,或者是一个变量名数组或 Fmi2Variable 类 对象的数组。指定的变量必须是字符串变量。

values 应该是相应变量的字符串值数组。变量数组和值的数组的长度必须相同。此方法需要已实例化的FMU。

Fmi2Import.setValue(variables, values)

此方法将FMU变量的值设置为指定的值。如果成功,则返回 true,如果值被FMU拒绝,则返回 false。这通常是由于数值原因:设置了超出范围的值,积分器无法收敛等。

variables 应该是一个 Fmi2VariableArray 对象,或者是一个变量名数组或 Fmi2Variable 类 对象的数组。指定的变量可以是任何类型。values 应该是相应变量的值数组。变量数组和值的数组的长度必须相同,且值的类型必须与相应的变量定义匹配。此方法需要已实例化的FMU。

Fmi2Import.getReal(variables)

此方法返回一个包含指定FMU变量值的数组。variables 应该是一个变量名数组,一个 Fmi2Variable 类 对象数组,或一个 Fmi2VariableArray 对象。指定的变量必须是实变量。此方法需要已配置的FMU。

Fmi2Import.getInteger(variables)

此方法返回一个包含指定FMU变量值的数组。variables 应为变量名称的数组、Fmi2Variable类对象的数组或一个Fmi2VariableArray对象。指定的变量必须是整数或枚举变量。此方法需要设置FMU。

Fmi2Import.getBoolean(variables)

此方法返回一个包含指定FMU变量值的数组。variables 应为变量名称的数组、Fmi2Variable类对象的数组或一个Fmi2VariableArray对象。指定的变量必须是布尔变量。此方法需要设置FMU。

Fmi2Import.getString(variables)

此方法返回一个包含指定FMU变量值的数组。variables 应为变量名称的数组、Fmi2Variable类对象的数组或一个Fmi2VariableArray对象。指定的变量必须是字符串变量。此方法需要设置FMU。

Fmi2State Fmi2Import.getState()

此方法返回一个表示当前FMU状态的 Fmi2State 对象。它可以作为 Fmi2Import.setState(state) 的参数使用,以从先前保存的状态恢复FMU。此方法需要一个实例化的FMU。

Fmi2Import.setState(state)

此方法将FMU状态恢复到在 Fmi2State类 对象 state 中保存的状态。此方法需要一个实例化的FMU。

Fmi2Import.terminate()

此方法终止当前模拟并将当前FMU状态更改为 Fmi2Import.Terminated。此方法需要一个初始化的FMU,且不在 Fmi2Import.Error 状态。

Fmi2Import.reset()

此方法将FMU恢复到 Fmi2Import.Instantiated 状态。此方法需要一个实例化的FMU。

Fmi2Import.doStep(stepSize, noPriorState)

此方法在CoSimulation模式下执行模拟步骤。它通过stepSize增加内部FMU模拟时间 Fmi2Import.time。如果模拟步骤正确执行,则返回 true;如果无法完成模拟步骤,则返回 false。这通常是由于数值原因发生的;即,内部FMU积分器没有收敛。回到之前保存的状态并使用修改后的输入重新尝试模拟步骤可能会成功。此方法需要一个初始化的FMU。

可以指定一个可选参数 noPriorState,它通知FMU它将不再恢复到在当前FMU时间之前的时间的状态。FMU可以用作清除缓存缓冲区的提示。此参数的默认值是 true

Fmi2Import.run(runtime, stepSize, timeFactor)

Fmi2Import.run(runtime, stepSize)

此方法执行一系列 stepSize 的模拟步骤。模拟将继续进行,直到内部FMU时间增加 runtime 或直到无法执行模拟步骤,在这种情况下,此方法返回 false。此方法需要一个初始化的FMU。

可选参数timeFactor用于控制模拟步骤执行的速度。它提供了模拟时间与模拟执行时间之间的关系。例如,如果时间因子等于0.5,则两秒的模拟时间应该在执行时间一秒内完成。对于与外部软件交互的实时系统模拟,timeFactor1可能最为有用。此参数的默认值为0——模拟步骤将以环境和FMU允许的速度执行。

注意:Squish不能执行比FMU和执行环境允许的更快的模拟。如果模拟运行速度低于请求的速度,请考虑增加步长以减少FMU交互频率。

Fmi2Import.runDetached(stepSize, timeFactor)

Fmi2Import.runDetached(stepSize)

此方法执行一系列模拟步骤,步长为stepSize,就像Fmi2Import.run(runtime, stepSize, timeFactor)。区别在于,该方法立即返回并执行模拟,同时并行于其他测试脚本的执行。在模拟过程中遇到的任何错误都通过Fmi2Import.sync()方法报告。此方法需要一个初始化的FMU。

Fmi2Import.sync()

如果FMU通过Fmi2Import.runDetached(stepSize, timeFactor)启动脱机模拟,它将等待请求的模拟步骤执行完毕,并在模拟提前中断时返回false。如果在模拟过程中遇到错误,则抛出异常。

Fmi2Variable类

Fmi2Variable类表示一个由FMU公开的变量。

Fmi2Variable.name

此只读属性包含变量名。

Fmi2Variable.value

此属性包含变量的当前值。如果FMU尚未准备好提供变量值(即未完全初始化),则结果为默认空值——数值类型为零,布尔变量为false,字符串变量为空字符串。

此属性为只读。要更改输入变量的值,请使用Fmi2Import.setValue(variables, values)或类型特定的Fmi2Import.set*方法。

Fmi2Variable.description

此只读属性包含一个可读的变量描述。

Fmi2Variable.valueReference

此只读属性包含变量的值引用。值引用是一个整数,由FMU内部用于识别变量。别名变量使用与其基本变量相同的值引用,因此始终具有相同的值。

Fmi2Variable.declaredType

如果变量有声明类型,则此只读属性包含Fmi2Type类类型的对象,否则为null

Fmi2Variable.baseType

此只读属性包含描述变量基本数据类型的值。它可以是一个

  • Fmi2Import.Real——一个实数变量
  • Fmi2Import.Integer——一个整数变量
  • Fmi2Import.Boolean——一个布尔变量
  • Fmi2Import.String — 一个字符串变量
  • Fmi2Import.Enum — 一个枚举变量

Fmi2Variable.hasStart

这个只读属性包含一个布尔值,表示该变量是否有一个已定义的启动值。

Fmi2Variable.variability

这个只读属性包含一个值,描述了何时允许变量值的变化。它可以是指定的其中之一

  • Fmi2Variable.Constant — 变量的值永远不会改变
  • Fmi2Variable.Fixed — 变量的值在FMU初始化后保持不变
  • Fmi2Variable.Tunable — 值不能在事件之间(模型交换)或仿真步骤之间(协同仿真)改变
  • Fmi2Variable.Discrete — 值不能在事件之间(模型交换)或仿真步骤之间(协同仿真)改变
  • Fmi2Variable.Continuous — 对值的变化没有限制
  • Fmi2Variable.UnknownVariability — 未知的可变性

Fmi2Variable.causality

这个只读属性指示变量值的获取方式。它可以是指定的其中之一

  • Fmi2Variable.Parameter — 一个独立参数;可以由测试脚本设置
  • Fmi2Variable.CalculatedParameter — 在FMU模型初始化期间或在参数更改后进行计算
  • Fmi2Variable.Input — 一个输入变量;可以由测试脚本设置
  • Fmi2Variable.Output — 一个输出变量
  • Fmi2Variable.Local — 内部FMU变量
  • Fmi2Variable.Independent — 模拟的一个独立变量。所有其他变量都定义为独立变量的函数。默认独立变量是 '时间'。一个FMU中最多只能有一个独立变量
  • Fmi2Variable.UnknownCausaility — 未知的原因

Fmi2Variable.initial

这个只读属性包含一个值,表示变量初始值的获取方式。它可以是指定的其中之一

  • Fmi2Variable.Exact — 使用start属性作为初始值
  • Fmi2Variable.Approx — 通过迭代计算初始值。使用start属性作为计算的初始值
  • Fmi2Variable.Calculated — 初始值是在初始化期间从其他变量的值计算出来的

Fmi2Variable.previous

这个只读属性包含一个Fmi2Variable,它包含变量的上一个值,或者如果没有定义此类变量,则包含null

Fmi2Variable.isAlias

这个只读属性包含一个布尔值,表示如果变量是另一个变量的别名,则为真

Fmi2RealVariable Fmi2Variable.asReal()

如果变量的baseTypeReal,则此方法将该变量转换为Fmi2RealVariable对象,否则为null

Fmi2IntegerVariable Fmi2Variable.asInteger()

如果变量的baseTypeInteger,则此方法将该变量转换为Fmi2IntegerVariable对象,否则为null

Fmi2EnumVariable Fmi2Variable.asEnum()

此方法将变量强制转换为 Fmi2EnumVariable 对象,如果其 baseTypeEnum,否则是 null

Fmi2StringVariable Fmi2Variable.asString()

如果变量的 baseTypeString,则此方法将变量强制转换为 Fmi2StringVariable 对象,否则是 null

Fmi2BooleanVariable Fmi2Variable.asBoolean()

如果变量的 baseTypeBoolean,则此方法将变量强制转换为 Fmi2BooleanVariable 对象,否则是 null

Fmi2RealVariable.start

Fmi2IntegerVariable.start

Fmi2EnumVariable.start

Fmi2StringVariable.start

Fmi2BooleanVariable.start

这些只读属性持有变量的适当类型的起始值。

Fmi2RealVariable.min

Fmi2RealVariable.max

Fmi2IntegerVariable.min

Fmi2IntegerVariable.max

Fmi2EnumVariable.min

Fmi2EnumVariable.max

这些只读属性持有变量的最小和最大值。

Fmi2RealVariable.derivativeOf

此只读属性持有变量是其导数的 Fmi2RealVariable 对象,如果没有则为 null

Fmi2RealVariable.unit

如果为变量定义了,则此只读属性持有 Fmi2Unit 对象,否则为 null

Fmi2RealVariable.displayUnit

如果为变量定义了,则此只读属性持有 Fmi2DisplayUnit 对象,否则为 null

Fmi2Type 类

Fmi2Type 类包含有关 FMI 类型定义的信息。它仅充当信息角色。

Fmi2Type.name

此只读属性持有类型定义的名称。

Fmi2Type.description

此只读属性持有类型定义的描述。

Fmi2Type.baseType

此只读属性持有类型定义的基本类型。此值的含义与 Fmi2Variable.baseType 相同。

Fmi2Type.quantity

此只读属性持有描述类型定义数量的一串字符。

Fmi2RealType Fmi2Type.asReal()

如果其 baseTypeReal,则此方法将类型定义强制转换为 Fmi2RealType 对象,否则为 null

Fmi2IntegerType Fmi2Type.asInteger()

此方法如果类型定义的 baseTypeReal,则将其转换为 Fmi2ItegerType 对象;否则为 null

Fmi2EnumType Fmi2Type.asEnum()

如果类型定义的 baseTypeEnum,则将类型定义为 Fmi2EnumType 对象;否则为 null

Fmi2Unit 类

Fmi2Unit 类包含有关 FMI 单位定义的信息。每个 Fmi2Unit 类可以有一个或多个相关的 Fmi2DisplayUnit 对象。显示单位用于以用户友好的格式显示值。这两个类都仅具有信息作用。

Fmi2Unit.name

此只读属性保存了单位定义的名称。

Fmi2Unit.displayUnits

此只读属性保存了与单位定义相对应的 Fmi2DisplayUnit 对象数组。

Fmi2Unit.SIexponents

此只读属性保存了一个整数数组,描述单位定义的 SI 指数。

Fmi2Unit.SIfactor

Fmi2Unit.SIoffset

这些只读属性保存了一个与相应 SI 单位对应的因子和偏移量。

Fmi2Unit.fromSI(value)

此方法将对应 SI 单位表示的值转换为指定单位中的值。

Fmi2Unit.toSI(value)

此方法将指定单位表示的值转换为对应 SI 单位中的值。

Fmi2DisplayUnit.name

此只读属性保存了显示单位定义的名称。

Fmi2DisplayUnit.baseUnit

此只读属性保存了一个关联的 Fmi2Unit 对象。

Fmi2DisplayUnit.factor

Fmi2DisplayUnit.offset

这些只读属性保存了一个与相应 Fmi2Unit 对应的因子和偏移量。

Fmi2DisplayUnit.fromDisplayUnit(value)

此方法将对应 Fmi2Unit 表示的值转换为显示单位中的值。

Fmi2DisplayUnit.toDisplayUnit(value)

此方法将显示单位表示的值转换为对应 Fmi2Unit 单位中的值。

Fmi2State 类

有些 FMUs 具有存储其当前状态和从之前保存的状态恢复的能力。 Fmi2State 代表一个存储的 FMU 状态。

您可以通过使用带有 Fmi2Import.CS_canGetAndSetFMUstate 标志的 Fmi2Import.getCapability(capability) 方法来查询 FMU 保存和恢复状态的能力。另外,具有 Fmi2Import.CS_canSerializeFMUstate 能力标志设置的 FMUs 可以将此类状态序列化为字节序列,该序列可用于在 FMU 实例之间传输。

Fmi2DisplayUnit.size

这个只读属性包含一个字节数组的容量,该数组可以存储序列化的状态数据。

Fmi2State.serialize()

此方法将表示的状态序列化,并将其作为一个字节数组返回。

示例

运行仿真

以下示例代码展示了如何加载FMU对象、访问其变量并运行仿真过程。

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
}

与 AUT 并行运行的仿真

在工具进程中创建了一个 FMU 对象。如果测试脚本访问 FMU 和 AUT,则必须更改当前上下文以与当前访问的对象匹配,具体描述在 如何在单个测试脚本中启动并访问多个应用被测对象 中。

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

等待仿真结果

要等待仿真变量达到特定值,请使用 Object waitForObject(objectOrName)。如果指定了 value 属性,它将仅查找指定值的变量,并在没有此类变量的情况下等待。

// 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'}" ]

如果等待的条件更复杂,可以使用 Boolean waitFor(condition) 函数。

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 } ]

如果感兴趣的变量在相对较短的时间内具有预期值,由于测试脚本执行的并行性质,有可能会完全错过该值。为了获得仿真过程的精细控制,请直接从测试脚本运行该变量。

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. 本文档的贡献权属于各自的拥有者。
提供的文档根据 Free Software Foundation 发布的 GNU Free Documentation License 1.3 版本的条款许可。
Qt 和相关的标志是 The Qt Company Ltd. 在芬兰和/或其他国家/地区的商标。所有其他商标归各自的所有者所有。