|
|
# 导入必要的模块和类
|
|
|
from app import create_app, db # 从app包导入Flask应用工厂函数和数据库实例
|
|
|
from app.models import MonitorPoint, AlarmRule, AlarmRecord # 导入数据模型类
|
|
|
from datetime import datetime, timedelta # 导入日期时间处理模块
|
|
|
import random # 导入随机数生成模块
|
|
|
|
|
|
def create_alarm_data():
|
|
|
"""
|
|
|
创建报警测试数据的主函数
|
|
|
这个函数会为每个监控点创建报警规则,并生成模拟的报警记录
|
|
|
"""
|
|
|
|
|
|
# 创建Flask应用实例
|
|
|
# create_app()是应用工厂函数,返回配置好的Flask应用对象
|
|
|
app = create_app()
|
|
|
|
|
|
# 使用应用上下文来执行数据库操作
|
|
|
# app.app_context()确保我们在Flask应用上下文中工作,这是访问数据库所必需的
|
|
|
with app.app_context():
|
|
|
# 第一步:清理现有的报警数据
|
|
|
# 先删除报警记录,再删除报警规则(由于外键约束,需要按顺序删除)
|
|
|
AlarmRecord.query.delete() # 删除所有现有的报警记录
|
|
|
AlarmRule.query.delete() # 删除所有现有的报警规则
|
|
|
|
|
|
# 第二步:获取所有监控点
|
|
|
# MonitorPoint.query.all() 查询数据库中的所有监控点
|
|
|
points = MonitorPoint.query.all()
|
|
|
|
|
|
# 检查是否已存在监控点数据
|
|
|
if not points:
|
|
|
print("请先创建监控点数据!")
|
|
|
return # 如果没有监控点,则退出函数
|
|
|
|
|
|
# 第三步:为每个监控点创建报警规则
|
|
|
rules = [] # 创建一个空列表来存储所有创建的报警规则对象
|
|
|
|
|
|
# 遍历每个监控点
|
|
|
for point in points:
|
|
|
# 为当前监控点创建溶解氧报警规则
|
|
|
rules.append(AlarmRule(
|
|
|
point_id=point.id, # 关联监控点ID
|
|
|
parameter='dissolved_oxygen', # 监控参数:溶解氧
|
|
|
min_value=4.0, # 最小值阈值
|
|
|
max_value=8.0, # 最大值阈值
|
|
|
level='warning', # 报警级别:警告
|
|
|
enabled=True # 规则启用状态
|
|
|
))
|
|
|
|
|
|
# 为当前监控点创建pH值报警规则
|
|
|
rules.append(AlarmRule(
|
|
|
point_id=point.id,
|
|
|
parameter='ph_value', # 监控参数:pH值
|
|
|
min_value=6.5, # 最小pH值
|
|
|
max_value=8.5, # 最大pH值
|
|
|
level='danger', # 报警级别:危险
|
|
|
enabled=True
|
|
|
))
|
|
|
|
|
|
# 为当前监控点创建温度报警规则
|
|
|
rules.append(AlarmRule(
|
|
|
point_id=point.id,
|
|
|
parameter='temperature', # 监控参数:温度
|
|
|
min_value=20.0, # 最低温度
|
|
|
max_value=28.0, # 最高温度
|
|
|
level='warning',
|
|
|
enabled=True
|
|
|
))
|
|
|
|
|
|
# 为当前监控点创建氨氮报警规则
|
|
|
rules.append(AlarmRule(
|
|
|
point_id=point.id,
|
|
|
parameter='ammonia_nitrogen', # 监控参数:氨氮
|
|
|
min_value=0.1, # 最小氨氮值
|
|
|
max_value=0.5, # 最大氨氮值
|
|
|
level='danger',
|
|
|
enabled=True
|
|
|
))
|
|
|
|
|
|
# 为当前监控点创建浊度报警规则
|
|
|
rules.append(AlarmRule(
|
|
|
point_id=point.id,
|
|
|
parameter='turbidity', # 监控参数:浊度
|
|
|
min_value=10.0, # 最小浊度
|
|
|
max_value=30.0, # 最大浊度
|
|
|
level='warning',
|
|
|
enabled=True
|
|
|
))
|
|
|
|
|
|
# 第四步:保存所有报警规则到数据库
|
|
|
# 遍历规则列表,将每个规则对象添加到数据库会话中
|
|
|
for rule in rules:
|
|
|
db.session.add(rule) # 将规则对象添加到数据库会话
|
|
|
|
|
|
# 提交事务,将所有添加的规则实际保存到数据库
|
|
|
db.session.commit()
|
|
|
|
|
|
# 第五步:创建报警记录数据
|
|
|
now = datetime.utcnow() # 获取当前UTC时间
|
|
|
|
|
|
# 定义各参数的单位,用于生成阈值描述
|
|
|
parameter_units = {
|
|
|
'dissolved_oxygen': 'mg/L', # 溶解氧单位:毫克/升
|
|
|
'ph_value': '', # pH值无单位
|
|
|
'temperature': '℃', # 温度单位:摄氏度
|
|
|
'ammonia_nitrogen': 'mg/L', # 氨氮单位:毫克/升
|
|
|
'turbidity': 'NTU' # 浊度单位:NTU
|
|
|
}
|
|
|
|
|
|
# 创建活跃报警记录(状态为active的报警)
|
|
|
for _ in range(5): # 循环5次,创建5条活跃报警
|
|
|
rule = random.choice(rules) # 随机选择一个报警规则
|
|
|
|
|
|
# 确保规则有最小值和最大值定义
|
|
|
if rule.min_value is not None and rule.max_value is not None:
|
|
|
# 随机决定是低于最小值还是超过最大值
|
|
|
if random.choice([True, False]):
|
|
|
# 生成低于最小值的数据
|
|
|
value = rule.min_value - random.uniform(0.5, 2.0)
|
|
|
# 生成阈值描述文本
|
|
|
threshold_desc = f"低于最小值 {rule.min_value} {parameter_units.get(rule.parameter, '')}"
|
|
|
else:
|
|
|
# 生成超过最大值的数据
|
|
|
value = rule.max_value + random.uniform(0.5, 2.0)
|
|
|
threshold_desc = f"超过最大值 {rule.max_value} {parameter_units.get(rule.parameter, '')}"
|
|
|
|
|
|
# 创建报警记录对象
|
|
|
alarm = AlarmRecord(
|
|
|
point_id=rule.point_id, # 关联的监控点ID
|
|
|
rule_id=rule.id, # 触发的规则ID
|
|
|
parameter=rule.parameter, # 报警参数类型
|
|
|
current_value=round(value, 2), # 当前值,保留2位小数
|
|
|
threshold=threshold_desc, # 阈值描述
|
|
|
level=rule.level, # 报警级别
|
|
|
status='active', # 报警状态:活跃中
|
|
|
created_at=now - timedelta(minutes=random.randint(5, 120)) # 创建时间:5-120分钟前
|
|
|
)
|
|
|
db.session.add(alarm) # 将报警记录添加到数据库会话
|
|
|
|
|
|
# 创建已解决的报警记录(状态为resolved的历史报警)
|
|
|
for _ in range(20): # 循环20次,创建20条历史报警
|
|
|
rule = random.choice(rules) # 随机选择一个报警规则
|
|
|
|
|
|
if rule.min_value is not None and rule.max_value is not None:
|
|
|
# 同样随机生成超出范围的值
|
|
|
if random.choice([True, False]):
|
|
|
value = rule.min_value - random.uniform(0.5, 2.0)
|
|
|
threshold_desc = f"低于最小值 {rule.min_value} {parameter_units.get(rule.parameter, '')}"
|
|
|
else:
|
|
|
value = rule.max_value + random.uniform(0.5, 2.0)
|
|
|
threshold_desc = f"超过最大值 {rule.max_value} {parameter_units.get(rule.parameter, '')}"
|
|
|
|
|
|
# 生成随机的创建时间(1-30天前)
|
|
|
created_time = now - timedelta(days=random.randint(1, 30))
|
|
|
|
|
|
# 创建已解决的报警记录
|
|
|
alarm = AlarmRecord(
|
|
|
point_id=rule.point_id,
|
|
|
rule_id=rule.id,
|
|
|
parameter=rule.parameter,
|
|
|
current_value=round(value, 2),
|
|
|
threshold=threshold_desc,
|
|
|
level=rule.level,
|
|
|
status='resolved', # 报警状态:已解决
|
|
|
created_at=created_time, # 报警创建时间
|
|
|
resolved_at=created_time + timedelta(minutes=random.randint(10, 120)) # 解决时间:创建后10-120分钟
|
|
|
)
|
|
|
db.session.add(alarm)
|
|
|
|
|
|
# 第六步:提交所有报警记录到数据库
|
|
|
db.session.commit()
|
|
|
|
|
|
# 第七步:打印统计信息
|
|
|
rules_count = AlarmRule.query.count() # 统计报警规则总数
|
|
|
active_alarms = AlarmRecord.query.filter_by(status='active').count() # 统计活跃报警数
|
|
|
resolved_alarms = AlarmRecord.query.filter_by(status='resolved').count() # 统计已解决报警数
|
|
|
|
|
|
print('报警测试数据创建成功!')
|
|
|
print(f'已创建 {rules_count} 条报警规则')
|
|
|
print(f'已创建 {active_alarms} 条活跃报警')
|
|
|
print(f'已创建 {resolved_alarms} 条历史报警')
|
|
|
|
|
|
# 程序入口点
|
|
|
if __name__ == '__main__':
|
|
|
# 当直接运行此脚本时,执行创建报警数据的函数
|
|
|
create_alarm_data() |