Kingscada 的日报表这种东西光靠内置模板硬套是不够的。实际项目里甲方考核指标动不动就变今天要看温度班平均值明天要加一个流量累计量后天又说要把三号罐的液位跟二号泵的频率放到同一张报表里。所以这次分享一个很实用的做法不写死变量而是通过查询 Kingscada 任意一个变量来动态生成日报表和趋势曲线。整个案例直接使用 Kingscada 自带的历史数据不需要额外接数据库也不需要写复杂的脚本去转存数据。这篇内容主要面向正在做 SCADA 项目实施的工程师、维护阶段需要频繁调整报表的现场调试人员以及刚接触 Kingscada 但想少走弯路的新手。我会把数据存储机制、报表生成逻辑、趋势曲线绑定方法以及我踩过的坑都拆开讲。1. 项目背景与整体设计思路1.1 为什么日报表和趋势曲线是SCADA项目的刚需工厂里最常问的一句话就是今天的数据怎么样。日报表就是把变量在一天内的变化情况用数字方式汇总出来比如平均值、最大值、最小值、累计量。趋势曲线则是把同一批数据画成线让运行人员一眼看出波动趋势。很多项目上线初期只做实时监视运行一两个月后用户就会开始要求历史数据统计。从系统架构看SCADA 的数据流向通常是这样的IO服务器采集现场设备数据 → 实时数据库保存当前值 → 历史服务器按周期把变化数据写入历史存储 → 报表和趋势图从历史存储中读数据。Kingscada 的厉害之处在于把历史存储和查询接口做成了基础服务不需要我们再去搭一套时序数据库。1.2 案例核心逻辑查询任意变量→历史数据→报表/曲线传统做法是在报表模板里把变量一个一个拖进去变量一多维护工作量巨大。而且一旦工艺调整变量被删除或者重命名报表就要全部重新做。这次案例的思路不同。我们建立一个变量查询配置作为入口通过输入或选择任意一个变量名Kingscada 在内部通过查询接口获取该变量的历史数据再将这些数据填充到日报表模板和趋势曲线控件中。整个过程可以理解为以变量为主键查询变量名作为表单主键字段。这样带来的优势很明显新增变量时只要配置了历史记录就能立刻生成报表无需改模板。变量删除时报表不会崩溃只是显示无数据。同一套模板可以复用到多个变量比如一号罐日报表和二号罐日报表可以共用同一个模板只是传入的变量名不同。需求拆解到最后其实是两个核心问题怎么让任意变量都有历史数据可查这就是历史记录配置的问题。怎么按变量名动态查询历史数据并展示这就是查询接口和报表/曲线绑定的问题。把这两个问题解决掉整套逻辑就通了。接下来先说历史数据的来源。2. 核心概念Kingscada 的历史数据存储机制2.1 变量与历史数据的关系很多人刚接触时都会有个误解只要定义了变量Kingscada 就会自动存储它的所有变化数据。实际上不是。变量在实时数据库中是常驻的但历史存储不是默认开启的。在 Kingscada 的变量管理器中每个变量都有数据采集设置相关的属性。要按某个变量生成日报表或趋势曲线前提是它已经启用了历史记录。另外还需要设置采集方式定时采集按固定周期采样例如每 30 秒记录一次。变化采集只在数值变化超过阈值时记录适合平稳运行的工艺参数。实时采集按最小扫描周期记录适合快速变化的量。日报表通常对所有参与统计的变量都建议用定时采集周期至少是统计间隔的一半以下。如果每 5 分钟要出一个平均数据采样周期至少 30 秒到 1 分钟。周期太长平均值会失真。2.2 历史数据存储配置Kingscada 的历史数据最终会落到它的历史数据库中常见的是按天建表或按月建表的存储文件也支持配置为关系数据库如 SQL Server。但为了跟内置历史数据这个前提保持一致我在这个案例里用的是 Kingscada 自带的原生存档。需要注意的存储参数有这几个存储路径必须保证磁盘剩余空间充足建议按项目数据量估算至少留出半年的余量。存储周期决定了数据库文件的切分粒度。日存储周期就是每天一个文件方便日报表按天取数。存储时长可以设置数据保留天数比如 180 天。超过时间的数据会被清理除非做备份。我在项目里习惯把历史数据文件放在专门的数据盘不放在系统盘。系统盘一旦写入频繁操作系统本身会拖慢 IO 响应Severe 模式下采集延迟会被放大趋势曲线画出来明显有毛刺。2.3 查询接口与数据处理逻辑Kingscada 提供历史数据查询接口常见的有两类分析函数接口按时间段取出原始历史数据、平均值、最大最小值通常用于日报表统计。趋势访问接口按时间段取出连续曲线数据直接喂给趋势控件显示。日报表本质上是时间维度的聚合。一天 1440 分钟如果采样周期是 1 分钟那单变量就有 1440 个原始点。我们不是把这 1440 个点全塞到报表里而是聚合为每小时的平均值和一个日汇总行。有的项目还需要统计峰谷值出现的时间点这对设备健康分析很有用。所以日报表的核心处理逻辑是指定变量名和日期。把当天 00:00 到 23:59 的数据按小时切片。每 1 小时计算一次平均值、最大值、最小值、累计量。最后生成 24 行小时数据和一行日汇总。趋势曲线的处理逻辑则更简单直接按时间范围查询变量数据按时间顺序把数值点返回给曲线控件。控件负责画线和坐标轴我们只负责给数据源。两个功能一个偏重统计一个偏重视觉但底子都是历史数据查询。3. 日报表生成实操按任意变量动态生成3.1 第一步确认变量已开启历史记录且采集周期合理开始做报表之前先检查变量配置。我一般直接在变量管理器里筛选历史记录字段把所有需要参与日报表统计的变量统一检查一遍。假设我在做一个污水处理厂的项目需要生成溶解氧DO的日报表。变量名是DO_001_A单位是 mg/L。我在变量属性里设置采集周期30 秒。记录历史勾选。记录变化率不勾选因为 DO 在曝气阶段变化较缓变化记录不如定时记录均匀。死区0.1。如果 30 秒内数值变化不超过 0.1就不记录新值。然后我建一个测试界面放一个历史数据查询按钮先手动查询一下DO_001_A的历史数据确认确实有数据落盘。这一步非常关键。很多人报表里显示无数据根本不是报表模板的问题而是源头变量没有历史记录。3.2 第二步设计日报表模板日报表模板我建议用 Kingscada 的报表系统来做而不是用外部 Excel。理由有三个内置报表可以直接引用历史查询函数运行时不需要额外安装 Office。报表可以在 KingSCADA 运行环境中直接预览和打印。模板支持变量动态替换也就是变量名作为参数传入。模板结构如下表头项目名称、报表标题、日期。主体区域小时序号、平均值、最大值、最小值。汇总行日平均值、日最大值、日最小值。参数区日期参数、变量名参数。在模板单元格里填入查询表达式时我踩过一个大坑日期格式。Kingscada 内部历史查询接口默认使用yyyy-MM-dd HH:mm:ss格式模板里如果写成yyyy/MM/dd查询会静默失败不报错但返回空数据。所以日期参数一定要用标准格式而且最好设置单元格格式为文本避免自动转换。3.3 第三步通过变量名动态查询并填充数据这是这个案例最核心的一步。传统报表模板是固定写死某个变量名的动态查询的思路是在内存中维护一个当前变量名字符串报表模板根据这个字符串去拼装查询表达式。具体操作在全局变量里定义一个ReportVarName字符串变量。画面上放一个下拉框内容从变量管理器读取所有开启历史记录的变量名运行时用户选择即可。点击生成日报表按钮时先把ReportVarName赋值再调用报表填充接口。按钮对应的脚本逻辑大致是这样的# 设置当前查询变量名 SetReportParameter(VarName, ReportVarName); SetReportParameter(ReportDate, ReportDate); # 调用报表刷新 ReportRefresh(DailyReport_01);报表内部会根据ReportVarName去查询该变量当天的历史数据。查询表达式模板类似# 示意按变量名和日期区间查询小时聚合 QueryTrendData(ReportVarName, StartTime, EndTime, DataType);其中DataType可以取平均值、最大值、最小值。脚本里把每小时的平均值赋值给模板中对应行循环 24 次即可。我实际测试过一个包含 100 个变量的报表用动态方式生成时只需写一套模板运行时切换变量名即可。相较于传统逐变量维护报表工作量大概节省八成。3.4 第四步汇总与导出日报表生成后一般要做日汇总和月汇总。日汇总就是把 24 小时的平均再平均最大值取全天最大最小值取全天最小。累计量则需要单独处理如果变量是流量累计量查询接口可以直接返回时段累计值。导出方面我建议导出为 Excel 和 PDF 两种格式。Kingscada 内置报表支持直接导出PDF 适合存档和发给领导看。Excel 适合用户二次加工。有一个值得注意的问题如果当天数据还没结束报表生成时当天最后一个小时的统计数据是不完整的。我一般在脚本里加一个逻辑当前时间如果在 N 点 N 分之前最后一段数据不算只统计到上一个完整小时。比如现在是 14:20日报表只统计到 13:00 的完整小时数据。实测中这样做不会引起用户投诉因为趋势图一眼就能看出来截断位置。4. 趋势曲线生成实操查询任意变量绘制曲线4.1 趋势曲线控件选型Kingscada 的画面系统里内置了趋势曲线控件支持实时数据和历史数据两种数据源。做日报表配套的趋势曲线时我推荐用历史趋势控件因为它可以自由指定起始时间和结束时间适合查看任意时段的曲线。控件主要属性曲线数量可以叠加多条变量曲线方便对比。时间范围起始时间和结束时间。Y轴范围自动或手动。游标支持拖动查看时间点数值。项目要求通过查询任意变量生成趋势曲线本质就是把变量名作为参数传给趋势控件的数据源。Kingscada 控件支持通过脚本指定数据源变量这一点跟日报表的动态查询是同一套路。4.2 绑定历史数据源在画面里放置趋势控件后在属性面板中添加曲线。曲线名称可以随便起真正关键的是曲线对应的数据源绑定。如果是一条变量曲线直接在控件属性中把数据源类型设为历史库然后指定变量名。如果是多条曲线比如同时看温度和压力就在曲线列表中添加两条记录。动态切换变量时脚本写法大概是这样# 设置第一条曲线的数据源变量名 SetTrendDataSource(Trend1, 0, VarName1); # 设置第二条曲线的数据源变量名 SetTrendDataSource(Trend1, 1, VarName2); # 刷新曲线 TrendRefresh(Trend1);这里有个细节趋势控件在切换变量后必须刷新时间范围。如果控件的时间范围还停留在上一次的结束时间新数据可能显示不出来。我通常在设置变量后强制把时间范围设为从查询开始时间到当前时间确保曲线完整显示。4.3 自定义时间范围查询与控制趋势曲线跟日报表最大的区别就是时间粒度。日报表以天为维度趋势曲线则可能要看分钟级。所以趋势界面通常提供一个时间范围设置快速选择最近 1 小时、最近 8 小时、最近 24 小时。自定义选择日历控件选择起始日期和结束日期。时间段偏移比如昨天全天。实际做的时候我发现快捷选项很受欢迎。运行人员一般习惯点一下最近 24 小时就把曲线拉出来但需要准确查看某天某个异常点时就要用到游标。Kingscada 趋势控件支持游标跟随鼠标移动并在侧边显示该时刻的数值这个功能非常实用。另外要注意缩放。有的项目变量波动较大曲线被压缩成一条直带根本看不清细节。这时需要开启笛卡尔坐标缩放或者滚动缩放。我建议在趋势界面上预留缩放比例输入框让用户输入 Y 轴范围比如温度范围 10~30 度而不是依赖自动量程。4.4 多变量对比与显示优化真正在现场跑起来用户不会满足于一条曲线。最常见的是要看两条曲线的关联性比如循环水泵频率和管道压力的关系、PH 值和加药量的关系。多变量对比时要注意两点变量单位不同Y 轴如果共用一个坐标系需要归一化。我一般把每个曲线配置为独立 Y 轴但这样的坏处是两条曲线不在同一个视觉基准上对比不直观。所以有时我也先做归一化处理把值减去最小值再除以量程全部映射到 0~1 区间。每条曲线的颜色和线型要分开。颜色建议用红、蓝、绿三色线型用实线和虚线区分必要时加上数据点标记。实测中如果两条曲线的量级差得太大比如一个 0~10一个 0~1000即使开独立 Y 轴也难看清小量级曲线的波动。解决办法是右上角加一个曲线开关点击图例可以将某条曲线暂时隐藏。Kingscada 控件自带图例点击隐藏功能只需要在属性里打开。5. 常见问题与排查技巧实录5.1 报表显示无数据但趋势曲线正常这个问题我遇到过不下五次。趋势曲线正常说明变量历史数据存在报表却没数据通常不是数据源问题而是查询参数格式错误或报表模板行数不够。最典型的场景日期参数格式化字符串与系统区域设置不匹配。在中文系统上如果脚本直接用Now()函数赋值日期输出可能是2025-01-14 10:30:00但报表模板里按文本转换为日期时用了yy-mm-dd格式直接查询失败。解决办法是把日期格式统一封装成一个格式化函数所有地方调用同一个函数输出。5.2 趋势曲线出现断线或异常跳变曲线断线的常见原因是历史数据中有长时间空缺。比如变量配置了死区数值在死区范围内变化时没有记录新值但曲线控件默认使用线性插值导致出现台阶或斜线。处理方法如果跟踪参数在小范围内微调是正常现象建议不要设置死区或者把死区设得很小。如果断线比较多检查网络链路是否有断连。SCADA 前端 IO 服务器如果与设备控制器通信中断历史数据不会自动补传这块只能从采集侧排查。还有一个比较折腾的问题历史数据服务器时间跳变导致的数据错位。Kingscada 历史存储基于服务器本机时间如果现场有人手动改了系统时间那么这段时间内采集的历史数据的时间戳就乱了。排查时可能看到曲线横轴出现时间重复或倒序。这种问题最好从规范上杜绝禁止运行人员修改 SCADA 服务器系统时间并设置对时。5.3 动态查询时变量名带特殊字符导致脚本错误项目里的变量名有时候会带空格、中划线或点号比如PID-01.PV这种变量名直接拼接到查询表达式里会报错或查不到。处理办法是用 引用方式 包住变量名。Kingscada 脚本表达式里变量名如果包含特殊字符可以加方括号或引号。我在写动态查询参数时统一对变量名做一次清洗去掉首尾空格把中划线替换为下划线。如果无法替换就尝试用方括号包裹。反正尽量在定义变量名时就用纯字母、数字、下划线避免后面给自己挖坑。5.4 报表数据量过大导致生成卡顿一个大型项目可能有几千个变量如果用户一次性把所有变量都放到日报表里报表生成时查询量巨大UI 卡死几乎是可以预见的。我的建议是分页分批查询单个报表最多放 64 个变量统计。超过的话拆分到多个报表模板。查询时每小时的聚合查询拆成 6 个 10 分钟段全部都查出来后在内存里聚合避免在 UI 线程上一次性做大量 IO 操作。如果必须一次查大量数据考虑把查询封装到后台脚本通过异步消息返回结果。实测下来60 个变量、24 小时、每小时聚合一次的数据量在普通工控机上大约 0.8~1.5 秒就能生成完卡顿感基本可以忽略。5.5 我的一些额外建议再分享两个我在真实项目里总结的小技巧。第一个是趋势曲线默认时间范围。新控件属性里默认时间范围是当前时间很多用户刚打开画时看不到历史曲线以为出了问题。我在画面初始化脚本里会把时间范围设置为昨天 00:00 到今天 00:00这样打开就有一整天的数据直观很多。第二个是日报表日期默认值。报表界面打开时日期控件如果为空用户会不知道填什么。初始化时默认设置为昨天日期因为今天的报表还没完整数据默认昨天最合理。运行人员如果想看今天手动改一下就行。6. 从单变量到整站这套逻辑的扩展空间这个查询任意变量生成报表和曲线的思路实际项目里可以直接扩展到整站数据的组态不局限于单个页面。举个例子水厂的进出水流量日报表、每个泵站的电度日报表、各个处理单元的 ORP 趋势都可以共用一套模板。扩展时只需要在变量命名上做好规划。我的习惯是按工艺区域设备参数三层命名比如A1_BLP_PV表示 A1 区域旁流泵的压力值。命名规则统一后报表模板里还可以用通配符做模糊匹配一次生成同一类型所有设备的日报。我后来做过一个全厂 32 个流量计的流量日报就是靠这个方式一键生成的。另外不要忽略历史数据库的维护。Kingscada 自带历史数据用久了文件会越来越大。我建议每月定期做一次历史数据完整性检查随机抽几个变量对比实时记录和报表统计值偏差超过 1% 就要检查采集周期是否被意外改过或者存储文件是否出现损坏。再就是磁盘告警务必在服务器上配置磁盘空间监控低于设定值自动提醒否则数据写满以后历史记录静默丢失等用户回头查数据时才后悔莫及。回到一开始说的目标这套实现的价值不光是省了模板维护的时间更重要的是让使用者能自主地按任意变量快速出数据。运行人员不需要理解数据库也不需要改脚本选一个变量名点一下查询日报表和趋势曲线就出来了。这才是 SCADA 建设要达到的效果。上面写到的步骤和坑都是我实际调试中一步一步试出来的照着做基本稳。