一、工业SCADA的痛点与TDengine的适配性

很多人可能没听过SCADA,换个说法就是工厂里管各种设备的“实时大脑”——比如车间里的焊接机器人、加热炉、水泵这些设备,它要盯着每台设备的运行参数,比如电机温度、水泵压力,一旦出异常就得马上通知人。但传统的SCADA系统用普通数据库存数据的时候,经常碰到两个头疼的问题:一是数据太多,每台设备每秒可能上传好几个参数,一天下来就是几百万条记录,普通数据库查询慢;二是告警要自己写代码算,实时性差,经常错过处理时机。TDengine刚好是专门存时序数据(像设备参数这种随时间变化的数据)的数据库,完美适配SCADA的需求,不用自己折腾各种组件,能省很多事。

1.1 SCADA系统的核心需求

对工厂来说,SCADA要满足的核心需求其实很简单:第一是存数据要快,每秒能处理几十万条点位数据;第二是查数据要快,比如突然要找1小时内某台设备的所有温度数据,一秒内就得出结果;第三是告警要准,不能漏报也不能重复报,触发条件设置好后,实时性要够强。

1.2 TDengine的核心优势

TDengine专门针对时序数据优化,比MySQL这类通用数据库快好几倍,还自带简单的计算功能,不用额外搭Redis或者其他中间件,运维起来也简单。它的超级表(可以理解为数据模板)功能,特别适合SCADA的点位管理,不用每个点位单独建表,统一管理同一类点位就行。

二、点位建模:从物理点位到TDengine的表结构

点位是SCADA的最小数据单元,比如“车间1焊接机器人A01的电极温度”就是一个点位,建模的核心是把这些物理点位转化成适合TDengine存的结构,既要符合工厂的实际情况,又要利用好TDengine的特性。

2.1 点位的抽象逻辑

每个点位一般有几个固定属性:时间戳(必须,因为是时序数据)、参数值(比如温度的数值)、参数状态(正常/预警/告警),还有标签(比如所属设备的ID、类型、点位名称,方便后续查询分类)。举个实际例子,某汽车工厂焊接车间的10台机器人,每台有8个温度类点位,总共有80个点位,建模的时候就把它们归为一类温度点位,用TDengine的超级表来管理。

2.2 TDengine点位建模的示例

这里用Python做演示,因为大部分开发者都熟悉,代码有详细注释,新手也能看懂。

# 技术栈:Python + TDengine官方驱动
# 目的:演示SCADA点位建模与数据插入的完整流程
import taos
from datetime import datetime

# 1. 连接本地TDengine服务(提前装好服务,默认配置可直接连)
conn = taos.connect(host="127.0.0.1", port=6030, user="root", password="taosdata")
# 2. 创建专门存SCADA数据的数据库,避免和其他数据混存
conn.execute("CREATE DATABASE IF NOT EXISTS scada_db KEEP 365 DAYS")  # 数据保留365天
conn.execute("USE scada_db")

# 3. 创建超级表(温度点位的模板,所有温度类点位都用这个结构)
# TAGS是标签,用来分类,方便后续按设备查数据
create_stable_sql = """
CREATE STABLE IF NOT EXISTS device_temp (
    ts TIMESTAMP,       -- 时间戳,格式必须是YYYY-MM-DD HH:MM:SS.ms
    temp FLOAT,         -- 温度值,单位℃
    alert_state INT     -- 告警状态:0正常,1预警,2告警
) TAGS (device_id NCHAR(20), device_type NCHAR(20), point_name NCHAR(50))
"""
conn.execute(create_stable_sql)

# 4. 模拟插入3个点位的测试数据,对应不同设备
# 点位1:车间1焊接机器人A01的电极温度
point1 = (
    datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
    85.2,
    0,
    "robot_A01",
    "welding_robot",
    "electrode_temp"
)
# 点位2:车间1焊接机器人A02的电极温度
point2 = (
    datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
    92.5,
    0,
    "robot_A02",
    "welding_robot",
    "electrode_temp"
)
# 点位3:车间2加热炉B01的内部温度(故意设为预警状态)
point3 = (
    datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
    101.8,
    1,
    "furnace_B01",
    "heating_furnace",
    "internal_temp"
)

# 5. 把数据插入到对应的子表(每个点位自动生成一个子表,不用手动创建)
insert_sql = """
INSERT INTO scada_db.temp_robot_A01 USING device_temp TAGS ('robot_A01', 'welding_robot', 'electrode_temp') VALUES ('{}', {}, {})
INSERT INTO scada_db.temp_robot_A02 USING device_temp TAGS ('robot_A02', 'welding_robot', 'electrode_temp') VALUES ('{}', {}, {})
INSERT INTO scada_db.temp_furnace_B01 USING device_temp TAGS ('furnace_B01', 'heating_furnace', 'internal_temp') VALUES ('{}', {}, {})
""".format(point1[0], point1[1], point1[2],
           point2[0], point2[1], point2[2],
           point3[0], point3[1], point3[2])
conn.execute(insert_sql)

# 关闭连接
conn.close()
print("所有点位数据插入完成")

三、告警计算:从实时数据到触发告警的全流程

告警是SCADA的核心功能,原来需要自己写代码拉数据、算规则,现在用TDengine自带的查询就能快速完成,不用复杂的逻辑,还能保证实时性。

3.1 告警规则的定义

告警规则不用太复杂,工厂里常用的就是“参数超过阈值告警”,比如温度超过100℃预警,超过120℃严重告警;也可以设置“连续N次超过阈值告警”,比如10秒内连续3次温度上升触发预警,避免单次波动误报。

3.2 实时告警计算的示例

下面的代码演示如何用TDengine实现实时告警,同样是Python,和上面的代码兼容,方便扩展。

# 技术栈:Python + TDengine官方驱动
# 目的:演示SCADA实时告警计算,检查最近10秒的数据是否触发告警
import taos

# 1. 连接数据库
conn = taos.connect(host="127.0.0.1", port=6030, user="root", password="taosdata")
conn.execute("USE scada_db")

# 2. 定义告警阈值,根据工厂实际需求调整
ALERT_WARNING = 100.0  # 预警阈值
ALERT_CRITICAL = 120.0  # 严重告警阈值

# 3. 查询最近10秒的所有温度数据,高效筛选时间范围(TDengine的时序查询很适合这种场景)
query_sql = """
SELECT device_id, point_name, temp, ts 
FROM device_temp 
WHERE ts > NOW - 10s
"""
result = conn.query(query_sql)

# 4. 遍历数据,生成告警信息(实际场景可以推送到企业微信、短信等)
alerts = []
for row in result:
    device_id, point_name, temp, ts = row
    if temp >= ALERT_CRITICAL:
        alerts.append(f"【严重告警】{ts} | 设备:{device_id} | 点位:{point_name} | 温度:{temp}℃")
    elif temp >= ALERT_WARNING:
        alerts.append(f"【预警】{ts} | 设备:{device_id} | 点位:{point_name} | 温度:{temp}℃")

# 5. 输出告警结果
if alerts:
    print("触发的告警:")
    for alert in alerts:
        print(alert)
else:
    print("最近10秒无异常告警")

conn.close()

四、技术优缺点与注意事项

4.1 TDengine在SCADA落地的优势

第一个优势是性能高,存时序数据的速度是MySQL的10倍以上,查询最近1小时甚至1年的数据都能在几十毫秒内出结果;第二个优势是组件少,不用搭配其他数据库,一套TDengine就能搞定存数据、算告警、查数据的所有需求,运维成本低;第三个优势是开发简单,不用写复杂的SQL,自带的函数就能做聚合计算,还有专门的驱动支持多种编程语言,新手也能快速上手。

4.2 TDengine在SCADA落地的不足

TDengine专门优化时序数据,对非时序的结构化数据(比如设备的型号、安装时间)支持不如MySQL,这类数据存到TDengine里会有点麻烦,需要额外的映射;如果是超大规模的SCADA系统,比如有上万个点位,TDengine的集群运维需要专业人员,中小工厂的话完全没问题。

4.3 落地时的注意事项

第一是点位建模要统一,标签的命名规则要固定,比如设备类型不能有的写“加热炉”有的写“heating_furnace”,不然查询的时候会乱;第二是时间戳要统一,必须用工厂的标准时间,不能有的用秒有的用毫秒,否则时间范围查询会出错;第三是告警规则要去重,比如同一个点位5秒内触发的告警只发一次,避免给运维人员发重复消息。

五、落地实践总结

TDengine在工业SCADA里的落地,核心是把点位建模和TDengine的特性结合,不用自己折腾数据库的底层优化,从点位建表到告警计算,全链路都能快速实现,特别适合中小工厂的监控场景。整个过程不用太专业的数据库知识,只要了解SCADA的点位逻辑,就能用TDengine搭建起稳定的实时监控系统,解决传统SCADA系统存数据慢、告警不及时的痛点。