======= 慧飞IOT球阀设备数据分析 — 冷启动文件 =======
> 版本: 2.1 | 日期: 2026-08-17 | 用途: 球阀设备数据分析工作流的冷启动/重建/排障手册
> 服务器: 腾讯云轻量 lhins-1dai07vu | 公网IP: 82.156.85.124 | 系统: Ubuntu | 时区: Asia/Shanghai
> 工作流名称: **慧飞IOT设备数据分析**(输入设备SN → 输出中文PDF分析报告)
> v2.1 更新: 报告开头增加**电池类型**(l_batcfg 配置码→36种电池规格对照)与**重启次数**(s_rt 回退检测)
> v2.0 更新: 表格全部改为文本段落、离线>2h+离线前信号、CSQ曲线、最后5天电池图、紧凑排版
---
====== 1. 工作流总览 ======
输入: 设备SN(如 863434084521977)
→ 查询设备档案(fa_device) + 位置(fa_work_facs)
→ 拉取历史数据(fa_work_facs_*_122_history_*) + 信号日志(fa_device_status_log)
→ 分析: 功耗异常 / 基站 / 充电 / 电压 / 高温 / 天气相关性 / 亏电原因
→ 生成 7 张 matplotlib 图表
→ 组装 HTML 报告 → LibreOffice 转 PDF
输出: 慧飞数字科技球阀设备{SN}数据分析报告.pdf(8页)
**一键命令:**
cd /home/ubuntu/huifei && ./venv/bin/python iot_full_report.py
约 2-4 分钟/台。产物在 /home/ubuntu/huifei/ 下。
====== 2. 环境与依赖 ======
- Python venv: `~/huifei/venv`(python3.11)
- 依赖: pymysql / matplotlib / pymupdf / pillow / rapidocr-onnxruntime(调试用)
- 中文字体: Noto Sans CJK(/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc)
- LibreOffice: soffice(headless 转 PDF)
- 历史分析脚本: iot_full_report.py(主)、iot_device_analysis.py、iot_deep_analysis.py
====== 3. 数据源(阿里云 PolarDB MySQL) ======
| 项 | 值 |
|----|-----|
| 主机 | hriotdata.mysql.polardb.zhangbei.rds.aliyuncs.com:3306 |
| 账号 | hfread(只读)|
| 库 | hriot |
| 白名单 | 服务器公网 IP 需在 RDS 白名单(服务器IP变化会连不上)|
**表结构关键点:**
- `fa_device`: id(PK), device_sn, project_id(122), hw_ver, sw_ver, **nb_model**(含"Air"=4G→前缀hr4gzxq;否则hrzxq), link_status, facs_id
- `fa_work_facs_{hr4gzxq|hrzxq}_122_history_{YYYY}_{MM}`: 按月分表!按 device_id 查询(有索引),**禁止全表扫描/去重**。字段: bat(电压), charge(充电状态), batlog(电流采样), update_time
- `fa_device_status_log`: **s_s_cell 是 JSON 字符串**——字段名是 **`eci`(不是cid!)**、pci、rsrp、rsrq、snr、tac、earfcn、band、mcc/mnc。eNodeB = eci >> 8
- `fa_work_facs`: 位置主表(name/lng/lat),通过 facs_id 关联
- batlog 格式: `{time,inter};`JSON头 + `;`分隔点,每点6字段: 电压V,电流mA(+放电/−充电),功率W,能量Wh,电量mAh,温度℃
====== 4. 判定规则(用户2026-08-16定稿) ======
| 项目 | 规则 |
|------|------|
| 功耗异常(持续) | 任意**1小时滑动窗口**内 **≥95% 时间点电流>20mA**;窗口≥15个采样点;事件间间隙≤15分钟自动合并 |
| 短时大电流 | **不抓取**(≥200mA单点尖峰如4G发射/阀门动作,用户明确不计)|
| 高温保护 | 设备温度 >62°C 且 charge=0(充电电路切断)|
| 充电判定 | 电流为负值=太阳能充电;涓流=电压>4.15V 且电流≤40mA |
| 低压关机 | 电压 <3V → 关机离线 |
| **离线时段** | **数据间隔 >2h** 即统计为离线;记录离线前最近一次上报的 RSRP/RSRQ/SNR/CSQ |
| 信号等级 | RSRP>-105良好 / -105~-115中等 / <-115较差;RSRQ>-10/-10~-15/<-15;SNR>10/0~10/<0 |
| 强/弱信号功耗 | RSRP>-105(强) vs ≤-105(弱) 功耗对比 |
| 亏电原因 | 6月1日为界对比前后充电天数占比+RSRP均值:6月后充电下降+信号无变化→农作物/杂草遮挡太阳能板或非法置物;信号变差→基站差频繁重连 |
| **电池类型** | fa_device_status_log.**l_batcfg**(电池配置码)→ 对照 **battery_cfg.json**(36种电池规格:1节18650 2900mAh ~ 12节并联34.8AH等);如 22=1节18650 金穗S1/普惠P1、27=1节21700(5000mAh) |
| **重启次数** | fa_device_status_log.**s_rt**(运行时间秒计数器)序列中"回退"(当前值 < 前值-1000)次数=重启次数 |
====== 5. 报告结构(8章+附件,数据全部文本段落展示,无表格) ======
1. 一、设备功耗异常分析(事件列表:开始 ~ 结束(持续 Xh))
2. 二、基站连接情况与功耗相关性(基站文本行:ID/Band/PCI/次数/RSRP/RSRQ/SNR/等级/功耗 + 子板块:同基站信号质量RSRP/RSRQ/SNR时间曲线含拐点 + CSQ曲线)
3. 三、太阳能充电全程评估(>50mA点数统计 + 最大充电电流TOP5 + 电压与充电电流同图)
4. 四、天气与设备温度相关性分析(气温/太阳辐射/日照 vs 设备温度 Pearson r + 三联图)
5. 五、电压趋势与关机离线(**离线>2h逐条列出,含离线前RSRP/RSRQ/SNR/CSQ** + 最后5天电池电压电流图)
6. 六、锂电池高温保护分析(2条高温>62°C&charge=0 + 3条最大充电电流charge=1含设备温度)
7. 七、长期亏电原因分析
8. 八、结论与建议
9. 附件:信号参数定义(文本形式)
**报告开头设备档案含:** 电池类型(配置码+规格描述,如"配置代码22 1节18650(金穗S1/普惠P1)")与重启次数(如"10次")——用于判断电池容量与设备功耗是否匹配。
**红线:** 禁"电池热损伤/更换电池"表述(用"高温充电保护中断/充电不足");PDF文件名无括号。
====== 6. 图表清单(9张,全部 width=640 嵌入) ======
| 文件 | 内容 |
|------|------|
| chart_voltage.png | 日均/最低电压趋势 + 3V关机线 |
| chart_signal.png | 功耗 vs RSRP/RSRQ/SNR 三联散点(含相关系数)|
| chart_enb.png | 各基站信号强度 vs 功耗(双轴柱状)|
| chart_enb_sig.png | 同基站信号质量时间曲线(3基站×RSRP/RSRQ/SNR,红点=跌破阈值拐点)|
| chart_csq.png | CSQ 信号质量指数随时间变化(良好/中等/差参考线)|
| chart_charge.png | 电压与充电电流双轴图 |
| chart_weather.png | 天气-设备温度三联图(气温散点/太阳辐射散点/晴阴雨对比)|
| chart_bat5d.png | **最后5天电池电压与电流(电压线+电流线双轴)** |
====== 7. 排障速查(血泪教训) ======
| 症状 | 原因与修复 |
|------|-----------|
| **表格轮廓线看不见** | soffice 默认对 .html 用 Writer/Web 过滤器不渲染边框!必须 `--infilter="HTML (StarWriter)"` |
| **表格数据换行/表头竖排** | LibreOffice 不认 CSS 类 white-space!单元格必须**内联** `style="white-space:nowrap"`;数值加 ` ` 前导防数字拆行(如8.9被拆成8/.9)|
| **数字+单位被拆**(32°C→32°+C) | 数字与单位之间用 ` ` 连接(°C/mA/h 等)|
| **表格占满640px浪费空间** | 列宽按内容收缩(时间列≈110px),`cellpadding="1"`,CSS padding 1px 3px;最彻底方案=**表格改文本段落**(div.box +
逐条)|
| **基站数=0** | s_s_cell 字段是 **eci** 不是 cid(cid 不存在→全部跳过)|
| **图表显示一半** | `max-width:100%` 无效,img 必须显式 `width="640"` |
| **旧图表复用上一台设备** | 每次运行启动时删除旧 chart_*.png(enb 图在无数据时不生成会残留)|
| **天气400** | Open-Meteo archive 数据只到**昨天**:end_date clamp 到 `today()-1天` |
| **零数据设备崩溃** | 设备从未上报(如测试登记)→ 先 COUNT 检查,直接提示"无数据无法分析" |
| **列宽不生效** | LibreOffice 用内容定列宽,th width 只是提示——**td 也要加 width**(动态表格全单元格加)|
====== 8. 服务器冷启动恢复步骤 ======
1. 装 python3-venv + pip install pymysql matplotlib pymupdf pillow
2. 装 LibreOffice(soffice)+ Noto CJK 字体
3. 恢复 ~/huifei/ 目录(脚本+venv)
4. 确认 PolarDB 白名单含服务器公网IP
5. 测试: ./venv/bin/python iot_full_report.py 863434084521977
====== 9. 已分析设备记录(供对比参考) ======
| SN | 位置 | 结果 |
|----|------|------|
| 863434084521977 | 许森林3839-田块2-16-3 | 2个持续放电事件、123次高温保护、5基站、电压健康 |
| 863434082193639 | 李爱玲测试-3-1 | 健康(旧规则6事件实为假阳性,新规则0)|
| 863434082157261 | 新疆 84.128E | 弱信号耗电2.1倍(旧报告)|
| 863434082206654 | 吴磊西红柿葫芦地-7-10 | 电池受损充不满、46天离线(旧报告)|
| 863434082158855 | 李爱玲测试-3-3 | 17次高温保护(旧报告)|
| 862288084652781 | 杨宏伟-田块2-1-1 | 健康(模板验证设备)|
> 注:2026-08-16 前的旧报告功耗异常事件数用旧规则(连续>20mA≥1h,有数据空洞假阳性bug),需用新规则重跑确认。