← 返回文档中心

脚本和公式

服务器应用程序有一个用于执行用户脚本的内置引擎。脚本用于计算通道值和状态,以及计算命令值。

配置适用版本V6.4更新时间2026-04-28负责人ScadaDoc

脚本和公式

服务器应用程序有一个用于执行用户脚本的内置引擎。脚本用于计算通道值和状态,以及计算命令值。

脚本被写入脚本配置数据库表。使用模板创建的项目已包含一组初始脚本,可以将其用作开发自己的脚本的示例。中实现的变量和函数脚本然后在表中调用输入公式输出公式的列通道桌子。要对通道执行公式计算,请选中启用公式柱子。

脚本创建规则

编写和使用脚本的一般规则:

  1. 脚本是根据以下内容编写的C#语言的语法。可以使用各种 .NET 框架类,例如 Math、DateTime 和 File。
  2. 新的常量、字段、属性和方法被添加到脚本表并在通道公式中可用。
  3. 如果至少一个脚本或公式包含错误,服务器将无法运行。有关脚本错误的信息写入服务器应用程序日志中。

通道公式计算规则:

  1. 通道的输入公式输入输入/输出仅当服务器收到该通道的新数据时才计算类型。如果数据来自设备,请使用提到的通道类型。
  2. 通道的输入公式已计算计算/输出类型在主服务器循环的每次迭代中连续计算。计算顺序是通道数从小到大。如果某个通道的值和状态是根据其他通道的数据计算的,则使用计算通道类型。
  3. 通道的输出公式输入/输出,计算/输出输出类型是在向相应通道发送命令时计算的。
  4. 计算通道的输入公式后的通道状态输入输入/输出如果公式中未明确指定状态计算,则 types 等于传输到服务器的数据的状态。
  5. 对于通道已计算计算/输出类型,状态设置为定义如果公式中没有明确指定状态计算。
  6. 如果输入公式包含“;”符号,它分为两部分:第一部分计算通道值,第二部分计算通道状态。
  7. 如果通道有指定的限制,则在计算通道的输入公式后,将考虑限制来重新计算通道状态。
  8. 公式必须返回某些数据类型的值,如下所述。

通道输入公式返回以下类型的数据:

数据类型 描述
double 通道值
CnlData 通道值和状态
long 数据类型在 Channels 表中设置为 Integer 的通道的 64 位整数值
string 数据类型在 Channels 表中设置为 ASCII stringUnicode string 的通道字符串值

如果通道的输入公式返回上表中列出的数据类型以外的数据类型,则公式返回的值将根据通道的数据类型转换为适当的类型。通道输入公式中计算通道状态的部分必须返回 type 的整数值int

通道输出公式返回以下类型的数据:

数据类型 描述
double 命令值。要取消命令,公式必须返回 double.NaN
CnlData 命令值。要取消命令,公式必须返回 CnlData.Empty
byte[] 二进制命令数据。要取消命令,公式必须返回 null
string 字符串命令数据。由 Server 转换为字节数组

可用变量

脚本引擎提供以下内置变量:

多变的 数据类型 描述
Timestamp DateTime 处理数据的时间戳 (UTC)
IsCurrent bool 处理后的数据是当前数据
CnlNum int 计算公式的通道号
Channel Cnl 计算公式的通道的属性
ArrIdx int 已处理数组元素的索引
Cnl, CnlVal double 计算前传输给Server的通道值
CnlStat int 计算前传输至Server的通道状态
CnlData CnlData 计算前通道数据传输至Server
Cmd, CmdVal double 计算前传送给服务器的命令值
CmdData byte[] 命令数据传输到服务器
CmdDataStr string 命令数据作为字符串

可用功能

脚本引擎提供以下内置函数:

功能 数据类型 描述
N(n) int 返回通道号 n。用于通道克隆
Val() double 公式通道的实际值
Val(n) double 通道n的实际值
SetVal(n, val) double 设置通道n的当前值
Stat() int 配方通道实际状态
Stat(n) int 通道n的实际状态
SetStat(n, stat) int 设置通道n的当前状态
Data() CnlData 公式通道实际数据
Data(n) CnlData n通道实际数据
SetData(n, val, stat) double 设置通道n的当前值和状态
SetData(n, cnlData) double 设置通道n的当前数据
NewData(val, stat) CnlData 创建一个新的通道数据实例
PrevVal() double 公式通道的前一个值
PrevVal(n) double 通道 n 的先前值
PrevStat() int 公式通道的先前状态
PrevStat(n) int 通道 n 的先前状态
PrevData() CnlData 公式通道历史数据
PrevData(n) CnlData 通道n的历史数据
Time() DateTime 公式通道的实际时间戳
Time(n) DateTime 通道n的实际时间戳
PrevTime() DateTime 公式通道的上一个时间戳
PrevTime(n) DateTime 通道 n 的前一个时间戳
Deriv(n) double 通道 n 的时间导数

项目模板中的函数

在基于标准模板创建的项目中,脚本表包含以下函数:

功能 数据类型 描述
GetBit(val, n) double 返回指定值的第 n 位
GetBit(cnlData, n) CnlData 返回一个通道数据,由第n位值和通道状态组成
GetBits(val, n, len) double 返回给定值的指定位
GetBits(cnlData, n, len) CnlData 返回由指定位的值和通道状态组成的通道数据
SetBit(val, n, isOn) double 设置指定值的第n位
SetBit(cnlData, n, isOn) CnlData 设置通道值的第n位,保持通道状态不变
GetByte(val, n) double 返回指定值的第 n 个字节
DataRel(offset) CnlData 相对于当前通道的通道数据
SetData() double 根据命令值设置当前通道数据
GetDefaultData(val) CnlData 获取计算通道的默认数据
Now() double 当前日期和时间为浮点数。使用服务器时区
UtcNow() double 当前日期和时间为浮点数。使用通用时区 (UTC)
UnixTime() long 当前 Unix 时间(以秒为单位)
EncodeDate(dateTime) double 将指定的日期和时间转换为Double类型的通道值
DecodeDate(val) DateTime 将通道值转换为日期和时间
EncodeAscii(s) double 将最长 8 个字符的 ASCII 字符串转换为浮点数
EncodeUnicode(s) double 将最长 4 个字符的 Unicode 字符串转换为浮点数
DecodeAscii(val) string 将指定值转换为最长 8 个字符的 ASCII 字符串
DecodeUnicode(val) string 将指定值转换为最长 4 个字符的 Unicode 字符串
Substring(s, startIndex, length) string 通过边界检查从字符串中提取子字符串
SplitAscii(getStringFunc) string 将 ASCII 字符串拆分为多个通道存储
SplitUnicode(getStringFunc) string 将 Unicode 字符串拆分为多个通道存储
EverySec(getDataFunc) CnlData 每秒执行指定的函数
EveryMin(getDataFunc) CnlData 每分钟执行指定的函数
EveryHour(getDataFunc) CnlData 每小时执行指定的函数
CountPulse(cnlNum) double 统计指定通道的脉冲数
HourStarted() bool 表示新的一小时已经开始。每个通道的结果为真一次
DayStarted() bool 预示着新的一天开始了。每个通道的结果为真一次
MonthStarted() bool 预示着新的一个月已经开始。每个通道的结果为真一次

其他脚本,包括用于计算平均值的脚本,可在GitHub

调试脚本

开发自己的脚本时,请遵循语法规则并检查脚本是否正常工作。如果Server服务启动时编译脚本失败,Server操作日志中会显示错误信息ScadaServer.log,编译后的源代码可以在CalcEngine.cs文件,位于服务器日志目录中。要开发复杂的公式,我们建议使用 Microsoft Visual Studio 或 Visual Studio Code。

公式示例

示例 1:从设备接收的通道值的线性变换。该公式用于通道输入类型。

10 * Cnl + 1

示例 2:通道 101 和 102 的值之和。状态从通道 101 中提取。该公式用于已计算类型。

Val(101) + Val(102); Stat(101)

示例3:用于计算类型通道的公式提取0th位来自通道 105 的数据。

GetBit(Data(105), 0)

示例 4:该公式每分钟将计数器增加 1,并在每小时开始时重置计数器。

EveryMin(() => HourStarted() ? 0 : Val() + 1)