# 输入数据放置指导(v0.1 · 2026-09-17) > 适用:把现场给的原始数据放进 `<安装目录>\data\raw\`。放完之后页面与重算链都读这里, > **放错一层目录、名字写错,后面所有摄入都会读不到**(不会报错,只会"页面没数")——所以先体检再放。 > > 配套工具: > * `python scripts/raw_data_check.py` —— **放置体检**(结构/命名/增量三清单/放置指导); > * `python scripts/place_raw_data.py --src <现场包目录>` —— 按映射表**自动落位**(落位前自动跑体检,冲突会拦下); > * `python scripts/scan_stations.py` —— 扫 `data/raw` 有哪些场站、各源类齐不齐。 --- ## 1. 正确的位置长什么样 ``` <安装目录>\data\raw\ ├─ README_把原始数据放这里.txt ← 说明文件可以留在这一层 ├─ 如东\ ← 场站目录(下一级目录名 = 场站;扫描按此辨识) │ ├─ scada_10min\ ← 平铺 <机组>.csv(WTG01.csv … WTG38.csv) │ ├─ scada_1min\ ← 平铺 <内部台号>.csv(01E.csv … 37B.csv) │ ├─ 故障报警\ ← 年度/季度 .xls + XML 报警导出 │ ├─ 风机故障记录\ ← 年目录 + 月度汇总表(.xls/.xlsx) + .rar + 现场照片 │ ├─ 油样报告\ ← **两级**:<台号>\<部件>\*.pdf │ ├─ windcms\ ← 振动线 CMS 原始导出:<包名>\measurement\<年>\<月>\\*_decode.json │ │ └─ 厂家报告\上海电气_月度\ ← 厂商月度振动评估报告(PDF 扫描件) │ └─ m5_cms_tcm\ ← 振动线 handoff 正本 + 厂家报告\ │ └─ 厂家报告\ └─ 西门子4.0技术资料\ ← 与场站并列的**共享**技术资料(本体层 kb_ingest 读它) ``` **判断标准只有一条**:摄入脚本按"源类目录 → 再往下一层就是文件"读。多套一层包名目录 (`scada_10min\10分钟数据\WTG01.csv`)等于没放。 ## 2. 每类源件的规则(体检器逐条查) | 源类 | 允许的后缀 | 结构要求 | 体检器会报什么 | |---|---|---|---| | `scada_10min` | `.csv` | 平铺,**每台一个文件**,名字 = 场配置里的机组号(WTG01…) | 缺台(按台取数会空白)、文件名不是本场机组、多套一层 | | `scada_1min` | `.csv` | 平铺,名字是**内部台号**(01E…37B) | 台数与场配置不符(1min 导出不用 WTG 名,故按台数判) | | `故障报警` | `.xls` `.xlsx` `.xml` | 不许多套层 | 后缀不在约定内 | | `风机故障记录` | `.xls` `.xlsx` `.rar` `.jpg` `.png` | 年目录 + 月度表 | 后缀不在约定内 | | `油样报告` | `.pdf` | **两级** `<台号>/<部件>/*.pdf` | PDF 直接躺在源类根下(维护页按台/部件分组,会分不出来) | | `windcms` | `.json` `.pdf` `.docx` | 含 `*_decode.json`(可套 `<包名>/measurement/…` 层) | 没有 `*_decode.json` ⇒ 振动侧无源可算 | | `m5_cms_tcm` | `.json` `.docx` `.pdf` `.md` | handoff 正本(`handoff_vibration_v2.json` / `component_history.json`)+ `厂家报告/` | 缺正本时**由观澜自算件顶上**(`scripts/rudong_fusion_handoff.py` / `scripts/component_history_build.py`);现场有正本则以正本为准 | ## 3. 增量放置(重点) **"增量"= 只补新数据,不要重放全量。** 放置工具与体检器都按**同名同尺寸**判断: | 情况 | 判定 | 处置 | |---|---|---| | 目标不存在 | **新增** | 拷进去 | | 目标存在、大小相同 | **相同(跳过)** | 不重复拷(源件是只读输入,同尺寸视为同一份) | | 目标存在、大小不同 | **冲突** | **必须人确认**:是"现场更正了数据"还是"这是另一批?" —— `place_raw_data.py` 默认**拒绝**落位,要覆盖需显式 `--force` | ```powershell # 1) 先看会新增/跳过/冲突什么(不写盘) python scripts\raw_data_check.py --src D:\现场增量包 # 2) 自动落位(落位前会再体检一次;有冲突会被拦下) python scripts\place_raw_data.py --src D:\现场增量包 python scripts\place_raw_data.py --src D:\现场增量包 --force # 确认要覆盖时才加 # 3) 落完再体检一次(含可读性抽样:CSV 编码/表头、TCM json 字段) python scripts\raw_data_check.py --deep ``` **为什么不让它悄悄覆盖**:源件是**只读输入**,覆盖不可逆;而台账类产物(报警 39,211 / 工单 5,876 / 油样 404)是逐行对齐源件的,覆盖后若没重算,页面与源件就对不上了。 ## 4. 放完之后做什么(体检器会按新增的源类给命令) ★ **不用自己记"放了什么"**(用户令 2026-09-19 增加自动扫描识别):放完直接看扫描结论 —— ``` python scripts\raw_scan.py --check # rc=0 无变化 · rc=4 有新数据(它会列出"该跑哪几步") · rc=5 还没基线 python scripts\rebuild_all.py --auto # 先扫一遍再重算: 新数据落在被 --skip-* 跳过的族里时自动取消跳过 ``` `--check` 的逐族口径是**指纹**(件数 / 体积 / 最新落盘时间 / 清单摘要 / **子目录清单**; 递归统计 `data/raw/<场>/<族>/**` 下**全部文件**(不限扩展名),白名单命中的件数另记 `matched`; `--deep` 再叠内容哈希),快照落在 `outputs\<场>\_raw_scan.json`,重算链第 **①b** 步每次都会顺手更新它。 ⇒ **文件的增/删(含嵌套子目录、含空目录的增删)都会被发现**;`data/raw` 里出现族表之外的目录/文件 会按"未归类、没有消费者"报出来,不猜它是哪一族。 若想让服务自己盯着(每 N 分钟扫一次、可选自动重算):`configs\serve.json` 的 `raw_watch` (默认关:`{"enabled": false, "minutes": 30, "auto_rebuild": false}`)。 ★ **尾月样本很少也如实出**(用户令 2026-09-20 裁决「保持现状」):实测补充件最后一个时间戳是 `2026-09-01 00:00`,于是 `temp_monthly` 里会多出一个**只有 1 行的 2026-09**,时间窗里也就多一格。 ### 4.1 现场按**类目**交付的月度通道组(2026-09-21 实测 7-8 月交付) 现场会按"月份 × 通道组"打包交付:`7月/风机数据.zip` → `2026-07-tur.mdb`,共 12 组 (中文目录 ↔ 类目码:`风机数据`=tur、`温度数据`=tmp、`压力数据`=prs、`电网数据`=grd、`DigiIn数据`=din、 `DigiOut数据`=dot、`计算数据`=cnt、`标志数据`=flg、`内部数据`=int、`统计数据`=scd、`标准数据`=std、`汇总数据`=sum)。 实测结论(2026-09-21,7 月交付): | 事 | 结论 | |---|---| | 落位 | `data/raw/<场站>/scada_mdb/<年>年/<月>月/<年>-<月>-<类>.mdb`(与既有 `2026-07-tur.mdb` 同规) | | 谁是消费者 | **取数层不直接读类目库**(它只认 `*-10min.mdb`/`*-1min.mdb`)⇒ 类目库是**上游归档**,扫描器按信息级列出、不计变化 | | 怎么才能被摄入 | 逐台类目表按 `TimeStamp+StationId` 对齐合成 **同台 10min 补充件** `scada_10min/<台号>-.csv`(列与主件逐列同名同序、时间戳 `YYYY-MM-DD HH:MM:SS`)⇒ 第 ③/④/④c 步自动纳入 | | 通道对应 | 9 个逐台类目与主件的**前缀块一一对应**(tur 91 / din 93 / dot 69 / cnt 69 / tmp 116 / prs 52 / grd 50 / flg 42 / int 13 = 595 通道,0 缺 0 多);`scd`/`std`/`sum` 是 farm 级与台账级,不在逐台 10min 布局内 | | 精度/格式 | 现场 CSV 导出是 **float32** 落盘、时间类通道写 `YYYY-MM-DD HH:MM:SS+00:00`;MDB 存 double / `MM/DD/YYYY HH:MM:SS` ⇒ 合成补充件时按 **float32 + ISO** 对齐,避免同一列跨日分层(实测重叠 19,555,865 格,两侧都有值却不等 = **0** 格) | ★ **`<场站>/scada_10min_.csv`(按月提取/核对件)**:用户指定放在场站目录下的交付核对件, **不是摄入源** ⇒ 扫描器按名字模式忽略(`IGNORE_PATTERNS`),不报"未归类"、不计入变化; 真正进产物的是 `scada_10min/<台号>.csv` + 同台补充件。 口径 = **产物是当前 `data/raw` 的函数** —— 源件里有这个时间戳就该看得见;加"最少样本"门会让 "数据到没到"变成猜的。要少这一格,把那个时间戳裁掉、或让现场别导出月初那一行即可。 ★ **产物 = 当前 `data/raw` 的函数**(用户令 2026-09-20「重算时要根据该目录最新的变化重算」): **删掉/换掉源件**后重算, 那些行就不再产出(脚本会大声报出"哪几个源件已不在盘、少了多少行、涉及哪些月", 好让人分清误删与现场撤数)。报警台账按**键集合并集**去重(键 = Name/Alarmcode/TimeOn), 所以累计快照件不会把同一事件算两遍,加减文件也不会让总数乱跳。 | 新增的源类 | 该跑的重算 | 预计 | |---|---|---| | `scada_10min` / `scada_1min` | `python scripts\rebuild_all.py` | 含 10 个构建器,约 15 分钟 | | **同台补充件**(如 `WTG01-B2.csv` 这种与主件命名不同的新月份件) | 同上 —— 2026-09-20 起取数层会**一并读入**:按列名对齐(新导出去掉了类型前缀 `din_wtc_X`→`wtc_X`)+ 按时间戳去重(主件优先);件名/各件行数/重叠数会打印并记在 `attrs` 里 | 同 ③ | | `故障报警` / `风机故障记录` / `油样报告` | `python scripts\rebuild_all.py --skip-scada` | 约 2 分钟 | | `windcms` / `m5_cms_tcm` | 同上(重算链第 ④b 步自动摄入索引/谱 + 报告/在升闭环/三层基线) | 按数据量(153 GB 导出约 25 分钟索引+谱) | | `scada_mdb`(现场年度归档库) | 同 `scada_10min`(CSV 缺失时取数层会回落到 MDB) | 同 ③/④/④c | | **删掉/换掉**上面任一类 | 同上(该族对应的那几步)—— 产物随之更新,删掉的行不再出现 | 同对应行 | | 只放了文档/技术资料 | 无需重算(不影响页面数值),但 `西门子4.0技术资料` 变了要重跑 ⑦ 本体层 | — | 重算后核对锚点:报警 **39211** · 工单 **5876** · 油样 **404** · `temp_monthly` **19494** · 本体 **9702** 对象(审计 0 问题); 页面看 `/detail/` 左栏「系统维护」两屏。若某页仍无数据,先看 `logs/ops/` 里最近一次动作的退出码。 ## 5. 常见错误(都是体检器实测报过的) | 现象 | 体检器的话 | 怎么修 | |---|---|---| | 把 csv 直接解到 `data/raw/` 根下 | `data/raw 顶层只放场站目录与说明文件; 源件要放进 <场站>/<源类>/` | 移进 `<场站>/scada_10min/` | | 多套了一层包名 | `未约定的子目录 (约定: [...]) —— 常见成因: 解压时多套了一层包名` | 把文件上提一层(`place_raw_data.py` 的映射表已按现场包结构写好,直接用它可以避免) | | 油样 PDF 平铺 | `N 个 PDF 直接躺在源类目录下 —— 约定是 <台号>/<部件>/*.pdf` | 按台号/部件建两级目录 | | 1min 目录被判"缺 38 台"(旧版本) | 已修:1min 用内部台号,按台数判完整 | 若台数确实不足,补齐对应台号的 csv | | 现场包被截断 | `不是合法 zip` | 重新拷贝现场包 | | 整包 zip 丢进场站目录 | `压缩包直接放在场站目录下 —— 先解压再按源类落位` | 解压后再放(或直接 `place_raw_data.py --src`) | ## 6. 规则表与本次体检结论 ### 体检结论(自动生成,勿手改) · 源件目录 `data/raw/如东`:26,325 件 / 177.64 GB - `m5_cms_tcm/`:1 件 / 20.8 MB - `scada_10min/`:38 件 / 14722.7 MB - `scada_1min/`:38 件 / 13074.1 MB - `windcms/`:25,693 件 / 153751.0 MB - `故障报警/`:16 件 / 22.7 MB - `油样报告/`:404 件 / 168.1 MB - `风机故障记录/`:135 件 / 142.3 MB · 结构与命名检查:**无不一致**(提示见下) · `i` data/raw/如东/m5_cms_tcm:缺 handoff 正本 (handoff_vibration_v2.json / component_history.json) —— 融合面判级与 /cms/ 改用**观澜自算**件(`scripts/rudong_fusion_handoff.py` / `scripts/component_history_build.py`,链上 ④b/④d);现场给了正本则正本优先 · `?` data/raw/如东:源件合计 177.6 GB —— 摄入与重算会很慢, 建议分批 **放置后该做什么**: · 没有新增源件: 不必重算 (若刚换过数据, 用 scripts/rebuild_all.py --dry-run 看计划) --- **退出码**(给脚本/CI 用):`0` 合规(可能带提示)· `5` 结构或命名违例 · `6` 增量冲突(同名不同大小)· `7` 缺源类或时间空洞 · `8` 仅有提示(体量/无消费者目录/散装件)。