风电场风力发电数据分析可视化系统 --- 技术文档
版本: 1.0 | 更新日期: 2026-06-21
1. 项目概述
基于 Flask 的风电场数据分析可视化平台,对 2019 年全年 35,040 条(15 分钟间隔)风电场运行数据进行多维分析、异常检测、产能效率评估和功率预测。
技术栈: Flask + SQLAlchemy + SQLite + ECharts 5.4.3 + NumPy + Pandas
代码规模: 6 个 Python 源文件(约 1,670 行)、19 个 HTML 模板(约 2,300 行)、1 个 CSS 文件(792 行),总计约 4,855 行。
2. 系统架构
┌─────────────────────────────────────────────────────────┐
│ 浏览器 (ECharts) │
├─────────────────────────────────────────────────────────┤
│ Flask 路由层 (app.py) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ 认证路由 │ │ 页面路由 │ │ 分析API │ │ 管理API │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘ │
│ │ │ │ │ │
│ ┌────▼─────────────▼─────────────▼──────────────▼────┐ │
│ │ SQLAlchemy ORM + NumPy │ │
│ └────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌────────────────────▼───────────────────────────────┐ │
│ │ SQLite (wind_farm.db) │ │
│ │ users 表 + wind_data 表 (35,040 行) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
数据流:
CSV (风电场_2019.csv) → init_db.py 批量导入 → SQLite
→ Flask API (SQL GROUP BY / NumPy 计算) → JSON
→ 前端 ECharts 渲染























3. 目录结构
cloud/
├── app.py # 主应用:所有路由和 API 逻辑 (1418 行)
├── models.py # SQLAlchemy 数据模型 (76 行)
├── config.py # 应用配置 (9 行)
├── init_db.py # 数据库初始化 + CSV 导入 (72 行)
├── requirements.txt # Python 依赖
├── wind_farm.db # SQLite 数据库 (11 MB)
├── 风电场_2019.csv # 原始数据 (35,040 行, 3.9 MB)
├── utils/
│ ├── __init__.py
│ └── prediction.py # 预测工具函数 (97 行)
├── templates/
│ ├── base.html # 基础布局 (侧边栏、顶栏、加载动画)
│ ├── login.html # 登录页
│ ├── register.html # 注册页
│ ├── index.html # 数据总览仪表盘
│ ├── profile.html # 个人中心
│ ├── analysis_wind_speed.html # 风速分析
│ ├── analysis_wind_direction.html # 风向分析
│ ├── analysis_power.html # 功率分析
│ ├── analysis_meteorological.html # 气象分析
│ ├── analysis_time_series.html # 时序分析
│ ├── analysis_correlation.html # 相关性分析
│ ├── analysis_advanced.html # 高级图表 (10 种)
│ ├── prediction.html # 功率预测
│ ├── anomaly_detection.html # 异常检测
│ ├── comparison.html # 月度对比
│ ├── production_efficiency.html # 产能效率分析
│ ├── data_manage.html # 数据管理 (admin)
│ └── user_manage.html # 用户管理 (admin)
└── static/
├── css/style.css # 暗色主题样式 (792 行)
└── img/wind-farm-bg.jpg # 登录页背景图
4. 数据库设计
4.1 用户表 users
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INTEGER | PK, 自增 | 用户 ID |
| username | VARCHAR(80) | UNIQUE, NOT NULL | 用户名 |
| password_hash | VARCHAR(256) | NOT NULL | Werkzeug 加密后的密码 |
| VARCHAR(120) | 邮箱 | ||
| phone | VARCHAR(20) | 手机号 | |
| avatar | VARCHAR(256) | DEFAULT '' | 头像 (emoji) |
| role | VARCHAR(20) | DEFAULT 'user' | 角色: user / admin |
| created_at | DATETIME | DEFAULT NOW | 注册时间 |
4.2 风电数据表 wind_data
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER (PK) | 记录 ID |
| timestamp | DATETIME (INDEXED) | 时间戳,15 分钟间隔 |
| wind_speed_10m | FLOAT | 10 米高度风速 (m/s) |
| wind_speed_30m | FLOAT | 30 米高度风速 (m/s) |
| wind_speed_50m | FLOAT | 50 米高度风速 (m/s) |
| wind_speed_70m | FLOAT | 70 米高度风速 (m/s) |
| wind_speed_hub | FLOAT | 轮毂高度风速 (m/s) |
| wind_dir_10m | FLOAT | 10 米高度风向 (°) |
| wind_dir_30m | FLOAT | 30 米高度风向 (°) |
| wind_dir_50m | FLOAT | 50 米高度风向 (°) |
| wind_dir_70m | FLOAT | 70 米高度风向 (°) |
| wind_dir_hub | FLOAT | 轮毂高度风向 (°) |
| temperature | FLOAT | 温度 (°C) |
| pressure | FLOAT | 气压 (hPa) |
| humidity | FLOAT | 湿度 (%) |
| power | FLOAT | 实际发电功率 (MW) |
4.3 数据库索引
sql
CREATE INDEX idx_wind_timestamp ON wind_data(timestamp);
CREATE INDEX idx_wind_power_ts ON wind_data(timestamp, power);
CREATE INDEX idx_wind_speed_ts ON wind_data(timestamp, wind_speed_hub);
idx_wind_timestamp: 支持所有时间范围查询和 ORDER BYidx_wind_power_ts: 覆盖索引,功率查询无需回表idx_wind_speed_ts: 覆盖索引,风速查询无需回表
5. API 接口文档
5.1 统一响应格式
json
// 成功
{"code": 0, "data": {...}}
// 错误
{"code": 1, "msg": "错误信息"}
// 分页
{"code": 0, "data": [...], "total": 35040, "page": 1, "limit": 20}
5.2 认证接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET/POST | /login |
登录,支持 JSON 和表单 |
| GET/POST | /register |
注册,首个用户自动成为 admin |
| GET | /logout |
退出登录 |
| GET/POST | /profile |
个人信息编辑(头像、邮箱、手机号、密码) |
认证方式:Session-based,使用 werkzeug.security 的 generate_password_hash / check_password_hash。
5.3 仪表盘
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/dashboard/summary |
总览统计 |
返回字段:total_records, date_range, avg_power, max_power, total_energy, avg_speed, avg_temp
5.4 分析接口
所有分析接口支持 ?month=YYYY-MM 参数筛选月份。
/api/analysis/wind_speed --- 风速分析
json
{
"monthly_avg": {"1": {"hub": 5.32, "10m": 4.10, "30m": 4.85, "50m": 5.12, "70m": 5.45}},
"frequency": {"labels": ["0-1", "1-2", ...], "values": [2.1, 5.3, ...]},
"time_series": {"timestamps": [...], "hub": [...], "10m": [...], "70m": [...]},
"stats": {"hub_avg": 6.28, "hub_max": 18.5, "hub_min": 0.0, "hub_std": 3.41}
}
/api/analysis/wind_direction --- 风向分析
json
{
"rose": {"labels": ["N","NNE",...], "frequency": {"N": 8.5, ...}, "avg_speed": {"N": 5.2, ...}},
"monthly_rose": {"1": {"N": 12.3, ...}, "2": {...}},
"heights": {"10m": {"N": 10.2, ...}, "hub": {"N": 8.5, ...}}
}
/api/analysis/power --- 功率分析
json
{
"curve": {"labels": ["0-1","1-2",...], "values": [0.0, 0.5, ...]},
"monthly_avg": {"1": 45.2, "2": 52.1, ...},
"monthly_sum": {"1": 33450.0, ...},
"distribution": {"labels": ["0.0-10.0",...], "values": [1200, ...]},
"time_series": {"timestamps": [...], "power": [...], "wind_speed": [...]},
"daily_energy": {"dates": ["2019-01-01",...], "values": [2850.5, ...]},
"stats": {"avg_power": 48.5, "max_power": 198.2, "total_energy": 425000.0, "capacity_factor": 24.3}
}
/api/analysis/meteorological --- 气象分析
返回月度均值、散点数据(温度-功率、湿度-功率、气压-功率)、时间序列、统计值。
/api/analysis/time_series --- 时序分析
支持 ?agg=hour|day|week|month 参数,返回聚合后的时间序列和自相关系数(滞后 1-48)。
/api/analysis/correlation --- 相关性分析
返回 10×10 相关系数矩阵和两组散点数据(轮毂风速-功率、温度-功率)。
/api/analysis/advanced --- 高级图表
一次返回 10 种图表数据:漏斗图、桑基图、河流图(堆叠柱状图)、箱线图、气泡图、季节小时模式、月度风玫瑰、累计发电量曲线、热力图、风速持续曲线。
/api/prediction --- 功率预测
json
{
"power_curve": {"speeds": [0,1,...,25], "powers": [0.0, 0.5, ...]},
"monthly": {"1": {"avg_speed": 5.32, "avg_power": 45.2, "total_power": 33450.0}},
"daily_forecast": {"historical_dates": [...], "historical_values": [...], "forecast_values": [...]},
"hourly_pattern": {"0": 32.1, "1": 28.5, ..., "23": 35.2},
"weibull": {"labels": ["0-1","1-2",...], "values": [2.1, 5.3, ...]}
}
5.5 数据洞察接口
/api/data/quality --- 产能效率分析
基于贝茨极限(Betz Limit, Cp=16/27)计算理论最大发电量,与实际发电量对比:
- 转换效率 = 实际功率 / 理论功率 × 100%
- 容量因子 = 实际发电量 / (额定功率 × 运行小时数) × 100%
- 损失电量 = 理论发电量 - 实际发电量
物理参数:空气密度 ρ=1.225 kg/m³,叶轮半径 R=40m,额定功率 200MW。
/api/anomaly/detection --- 异常检测
使用 IQR(四分位距)方法:
Q1, Q3 = np.percentile(values, [25, 75])
IQR = Q3 - Q1
异常范围: < Q1 - 1.5×IQR 或 > Q3 + 1.5×IQR
分别检测风速、功率、温度三个维度的异常值,返回时间线和分布数据。
/api/comparison --- 月度对比
返回月度发电量、风速、功率对比数据及环比变化率,标识最佳/最差月份。
5.6 管理接口
| 方法 | 路径 | 说明 | 权限 |
|---|---|---|---|
| GET | /api/data/list?page=1&limit=20&month=2019-03 |
分页数据列表 | admin |
| POST | /api/data/delete/<id> |
删除记录 | admin |
| POST | /api/data/update/<id> |
更新记录 | admin |
| GET | /api/user/list |
用户列表 | admin |
| POST | /api/user/add |
添加用户 | admin |
| POST | /api/user/update/<id> |
更新用户 | admin |
| POST | /api/user/delete/<id> |
删除用户 | admin |
| GET | /api/export/csv?month=2019-03 |
CSV 导出 | login |
6. 核心算法
6.1 功率曲线预测
使用 3 次多项式拟合风速-功率关系:
python
coeffs = np.polyfit(wind_speeds, powers, 3)
poly = np.poly1d(coeffs)
predicted = poly(predict_speeds)
predicted[predicted < 0] = 0 # 负值截断
6.2 风速频率分布(类 Weibull)
python
bins = np.arange(0, max_speed + bin_size, bin_size)
hist, edges = np.histogram(wind_speeds, bins=bins)
frequency = hist / len(wind_speeds) * 100 # 百分比
6.3 功率曲线(分箱均值)
python
bin_indices = np.digitize(wind_speeds, bins)
for i in range(len(bins)):
mask = bin_indices == i
curve[i] = np.mean(powers[mask]) if mask.any() else 0
6.4 加权移动平均预测
python
val = 0.5 * recent[-1] + 0.3 * recent[-2] + 0.2 * recent[-3]
基于最近 14 天数据,滑动窗口向前预测 7 天。
6.5 IQR 异常检测
python
q1, q3 = np.percentile(values, [25, 75])
iqr = q3 - q1
outliers = (values < q1 - 1.5 * iqr) | (values > q3 + 1.5 * iqr)
6.6 自相关分析
python
for lag in range(1, 49):
corr = np.corrcoef(speeds[:-lag], speeds[lag:])[0, 1]
用于检测风速的时间周期性。
6.7 产能效率(贝茨极限)
python
P_theoretical = 0.5 × ρ × A × v³ × Cp / 10⁶ # MW
# ρ = 1.225 kg/m³, A = π × 40² m², Cp = 16/27
efficiency = P_actual / P_theoretical × 100%
capacity_factor = E_actual / (P_rated × hours) × 100%
7. 前端设计
7.1 配色方案
深色数据分析主题,主色调为琥珀金:
| 变量 | 色值 | 用途 |
|---|---|---|
--bg-primary |
#0c0f14 |
页面背景 |
--bg-card |
#1a1f2b |
卡片背景 |
--accent-primary |
#f59e0b |
主色调(琥珀金) |
--accent-green |
#10b981 |
正向数据 |
--accent-red |
#ef4444 |
负向/异常 |
--accent-teal |
#14b8a6 |
辅助色 |
--text-primary |
#e8eaed |
主文本 |
--text-secondary |
#9aa0ad |
次文本 |
7.2 图表技术
- ECharts 5.4.3(CDN 引入)
- 图表类型:折线图、柱状图、面积图、雷达图、玫瑰图、散点图、箱线图、桑基图、漏斗图、河流图、热力图、持续曲线
- 所有图表支持响应式 resize
- 加载时显示骨架屏 shimmer 动画
7.3 布局结构
┌──────────┬──────────────────────────────┐
│ │ 页面标题栏 │
│ 侧边栏 ├──────────────────────────────┤
│ (240px) │ │
│ │ 页面内容区 │
│ 导航菜单 │ (卡片网格 / 图表容器) │
│ │ │
│ │ │
│ 用户信息 ├──────────────────────────────┤
└──────────┴──────────────────────────────┘
响应式断点:768px 以下侧边栏隐藏,图表网格变为单列。
8. 用户角色与权限
| 功能 | 普通用户 (user) | 管理员 (admin) |
|---|---|---|
| 查看仪表盘 | ✓ | ✓ |
| 所有分析页面 | ✓ | ✓ |
| 功率预测 | ✓ | ✓ |
| 个人中心 | ✓ | ✓ |
| 数据管理(CRUD) | ✗ | ✓ |
| 用户管理(CRUD) | ✗ | ✓ |
| CSV 导出 | ✓ | ✓ |
首个注册用户自动成为管理员(migrate_db() 中实现)。
9. 数据处理流程
9.1 数据导入
风电场_2019.csv (UTF-8-BOM)
↓ pandas read_csv(encoding='utf-8-sig')
↓ 列名映射(中文→英文)
↓ 时间戳解析 ('%Y/%m/%d %H:%M')
↓ bulk_save_objects (1000条/批)
↓
wind_farm.db (35,040 行)
9.2 查询优化策略
| 场景 | 策略 | 示例 |
|---|---|---|
| 月度/日度/小时聚合 | SQL GROUP BY | strftime('%m', timestamp) + .group_by() |
| 时间范围筛选 | 半开区间 [start, end) |
_month_filter() 辅助函数 |
| 大数据量展示 | 尾部截取 500 点 | records[-500:] |
| 散点图数据 | 等步长采样 | data[::max(1, len(data)//500)] |
| 缺失值标记 | 哨兵值过滤 | > -50 阈值,SQL 和 Python 双层过滤 |
9.3 能量计算
python
INTERVAL_HOURS = 0.25 # 15 分钟间隔
energy_MWh = sum(power) × 0.25
10. 部署与运行
10.1 环境要求
- Python 3.11+
- 依赖:Flask 3.0.0, Flask-SQLAlchemy 3.1.1, Werkzeug 3.0.1, pandas 2.1.4, numpy 1.26.2
10.2 启动步骤
bash
# 1. 安装依赖
pip install -r requirements.txt
# 2. 初始化数据库(首次运行)
python init_db.py
# 3. 启动应用
python app.py
# 访问 http://127.0.0.1:5001
10.3 数据库迁移
app.py 中的 migrate_db() 在启动时自动执行:
- 检查
users表是否有role列,无则添加 - 创建
wind_data表的三个索引 - 首个用户自动设为 admin
11. 已知限制
- SQLite 单写锁:并发写入时会排队,适合单用户或低并发场景
- scikit-learn 未使用 :
requirements.txt中列出但代码未引用,可移除 - User.to_dict() 重复定义 :
models.py中有两个同名方法,第二个覆盖第一个 - predict_monthly_power() 未使用 :
utils/prediction.py中定义但从未调用 - 硬编码物理参数:贝茨极限计算中的叶轮半径(40m)和额定功率(200MW)为假设值
- 单年数据:仅包含 2019 年数据,无法做跨年同比分析