

前面几篇把“边缘计算”“数据融合”“孪生联动”拆开了讲。这一篇把视角拉回到一个真实项目的完整生命周期:
从甲方一句“我想看看库房空气质量”,到最终在 3D 场景里点一下密集架就能看到 PM2.5、TVOC、CO₂、温湿度、霉变风险——全程不走弯路。
核心主线: 业务需求 → 现场勘测 → 设备选型 → 网络组网 → 边缘接入 → 空间建模 → 数据绑定 → 3D 可视化 → 联动规则 → 验收交付 → 运维迭代。
某县档案馆,文书库 + 特藏库,总面积约 800㎡。
甲方痛点很具体:
业务目标(不是技术目标):

指标 | 档案影响 | 监测目的 | 合规参考 |
|---|---|---|---|
PM2.5 / PM10 | 纸张磨损、污损 | 防尘 | GB 3095 环境空气质量 |
TVOC | 纸张酸化、胶黏剂老化 | 防污染 | GB/T 18883 室内空气质量 |
CO₂ | 人员活动、通风效果 | 通风评估 | ASHRAE 62.1 |
温湿度 | 霉变、脆化 | 防潮防高温 | JGJ 25 |
甲醛 | 新装修风险 | 防污染 | GB/T 18883 |
光照/UV | 纸张褪色 | 防光 | ISO 11799 |

区域 | 点位数量 | 安装位置 | 理由 |
|---|---|---|---|
文书库 A | 6 个 | 每 5 列 1 个,离地 1.5m | 覆盖均匀,避开空调直吹 |
特藏库 B | 2 个 | 柜内 + 柜外各 1 个 | 对比柜内外差异 |
技术用房 C | 2 个 | 工作台上方 1.2m | 人员活动区 |
公共区域 D | 1 个 | 走廊中部 | 背景值参考 |
设备 | 型号 | 协议 | 单价 | 选型理由 |
|---|---|---|---|---|
多气体传感器 | 以太网型 | Modbus TCP | 1800 元 | 同时测 PM2.5/PM10/TVOC/CO₂ |
温湿度记录仪 | PoE 型 | SNMP | 450 元 | 高精度,内置存储 |
甲醛传感器 | 独立型 | RS485 | 600 元 | 新装修区域专用 |
UV 传感器 | 模拟量 | 4–20mA | 300 元 | 防光监测 |
选型原则:
设备 | 型号 | 数量 | 单价 | 用途 |
|---|---|---|---|---|
PoE 交换机 | 8 口千兆 | 2 台 | 800 元 | 传感器供电+数据 |
边缘网关 | ARM Linux | 1 台 | 2500 元 | 协议转换+本地计算 |
监控主机 | 工控机 | 1 台 | 3500 元 | HONSOR-V1.0 平台 |
机柜 | 6U 壁挂 | 1 台 | 600 元 | 设备安装 |
[文书库 A]
├── 多气体传感器 × 6(PoE)
├── 温湿度记录仪 × 3(PoE)
├── 甲醛传感器 × 1(RS485)
└── UV 传感器 × 1(4–20mA)
│
└──→ [PoE 交换机 A] ──┐
│
[特藏库 B] │
├── 多气体传感器 × 2(PoE)│
└── 温湿度记录仪 × 2(PoE)│
│ │
└──→ [PoE 交换机 B] ──┼──→ [边缘网关] ──→ [监控主机]
│
[技术用房 C] │
├── 多气体传感器 × 2(PoE)│
└── 温湿度记录仪 × 1(PoE)│
│ │
└──→ [PoE 交换机 C] ──┘
[公共区域 D]
└── 多气体传感器 × 1(PoE)
│
└──→ [PoE 交换机 A]
[监控主机]
├── HONSOR-V1.0 平台
├── 3D 可视化引擎
├── 数据库(InfluxDB + MySQL)
└── Web 服务器(Nginx)组网要点:
# 边缘网关配置示例
connections:
- name: modbus_tcp_sensors
type: modbus_tcp
host: 192.168.1.100
port: 502
devices:
- id: AIR-A-01
type: multi_gas
registers:
pm25: {addr: 0x0001, type: float}
pm10: {addr: 0x0003, type: float}
tvoc: {addr: 0x0005, type: float}
co2: {addr: 0x0007, type: float}
- id: TH-A-01
type: temp_humidity
registers:
temp: {addr: 0x0001, type: float}
humi: {addr: 0x0003, type: float}
- name: snmp_sensors
type: snmp
version: v2c
community: public
devices:
- id: TH-A-02
oids:
temp: 1.3.6.1.4.1.2021.13.16.2.1.2.1
humi: 1.3.6.1.4.1.2021.13.16.2.1.2.2
- name: rs485_sensors
type: modbus_rtu
port: /dev/ttyS1
baud: 9600
devices:
- id: HCHO-A-01
type: formaldehyde
registers:
value: {addr: 0x0001, type: float}
- name: analog_sensors
type: analog
channels:
- id: UV-A-01
type: 4_20ma
range: [0, 100] # UV 指数// 边缘侧数据清洗伪代码
function cleanData(rawData) {
// 1. 量程过滤
if (rawData.pm25 < 0 || rawData.pm25 > 1000) {
return {quality: 'invalid', reason: 'out_of_range'};
}
// 2. 跳变抑制(5秒内变化超过50%视为异常)
const lastValue = getLastValue(rawData.asset_id, 'pm25');
if (lastValue && Math.abs(rawData.pm25 - lastValue) / lastValue > 0.5) {
return {quality: 'doubtful', reason: 'sudden_jump'};
}
// 3. 一致性校验(多传感器交叉验证)
const neighborValues = getNeighborValues(rawData.space_id, 'pm25');
const avg = calculateAverage(neighborValues);
if (Math.abs(rawData.pm25 - avg) / avg > 0.3) {
return {quality: 'doubtful', reason: 'inconsistent_with_neighbors'};
}
// 4. 物理合理性(湿度高时PM2.5可能偏高)
const humidity = getLatestValue(rawData.space_id, 'humidity');
if (humidity > 70 && rawData.pm25 < 10) {
return {quality: 'doubtful', reason: 'unreasonable_low_pm25'};
}
return {quality: 'good', value: rawData};
}CAD 图纸
↓(提取墙体、门窗、柱子)
SketchUp 粗模
↓(简化细节,保留关键结构)
Blender 精模
↓(添加材质、UV 展开、优化面数)
glTF/glB 格式
↓(压缩、LOD 生成)
3D 可视化引擎加载县档案馆
├── 3F
│ ├── 文书库A
│ │ ├── A区
│ │ │ ├── 01列
│ │ │ │ ├── 1.5m(传感器高度)
│ │ │ │ │ ├── TH-A-01(温湿度)
│ │ │ │ │ └── AIR-A-01(空气质量)
│ │ │ │ ├── 0.5m(底层)
│ │ │ │ └── 2.0m(顶层)
│ │ │ └── 02列
│ │ └── B区
│ └── 特藏库B
│ ├── 柜内
│ │ ├── CAB-01
│ │ │ └── TH-B-01
│ │ └── CAB-02
│ └── 柜外
│ └── AIR-B-01{
"scene_id": "county_archive_3f",
"version": "1.0",
"spaces": [
{
"space_id": "3F-WS-A-01-1.5",
"path": ["县档案馆", "3F", "文书库A", "A区", "01列", "1.5m"],
"position": {"x": 2.4, "y": 1.5, "z": 0.6},
"bounds": {"min": [2.0, 1.3, 0.5], "max": [2.8, 1.7, 0.7]},
"assets": [
{
"asset_id": "TH-A-01",
"type": "temp_humidity",
"metrics": ["temp", "humidity"],
"update_interval": 30
},
{
"asset_id": "AIR-A-01",
"type": "multi_gas",
"metrics": ["pm25", "pm10", "tvoc", "co2"],
"update_interval": 30
}
],
"visualization": {
"type": "volume",
"color_mapping": {
"metric": "pm25",
"ranges": [
{"min": 0, "max": 35, "color": "#00ff00"},
{"min": 35, "max": 75, "color": "#ffff00"},
{"min": 75, "max": 150, "color": "#ff9900"},
{"min": 150, "max": 500, "color": "#ff0000"}
]
}
}
}
]
}// Three.js 数据绑定伪代码
class DataDrivenRenderer {
constructor(scene, dataBus) {
this.scene = scene;
this.dataBus = dataBus;
this.bindings = new Map();
// 订阅数据更新
this.dataBus.on('data_update', (data) => {
this.updateObject(data);
});
}
// 绑定空间与数据
bindSpace(spaceId, object3D, metrics) {
this.bindings.set(spaceId, {
object: object3D,
metrics: metrics,
lastValues: {}
});
}
// 更新对象状态
updateObject(data) {
const binding = this.bindings.get(data.space_id);
if (!binding) return;
// 更新缓存值
binding.lastValues[data.metric] = data.value;
// 根据指标类型更新渲染
switch (data.metric) {
case 'pm25':
this.updatePM25Visualization(binding.object, data.value);
break;
case 'temp':
this.updateTemperatureVisualization(binding.object, data.value);
break;
case 'humidity':
this.updateHumidityVisualization(binding.object, data.value);
break;
}
// 更新信息面板
this.updateInfoPanel(data.space_id, binding.lastValues);
}
// PM2.5 可视化:颜色渐变 + 粒子效果
updatePM25Visualization(object, pm25) {
let color;
if (pm25 <= 35) color = 0x00ff00; // 优
else if (pm25 <= 75) color = 0xffff00; // 良
else if (pm25 <= 150) color = 0xff9900;// 轻度污染
else color = 0xff0000; // 重度污染
object.material.color.setHex(color);
object.material.emissive.setHex(color);
object.material.emissiveIntensity = 0.2;
// 添加粒子效果(污染严重时)
if (pm25 > 150) {
this.addParticleEffect(object, pm25);
}
}
}// 历史回放控制器
class HistoryPlayback {
constructor(dataSource, renderer) {
this.dataSource = dataSource;
this.renderer = renderer;
this.playbackSpeed = 1; // 1x, 2x, 5x, 10x
this.isPlaying = false;
this.currentTime = null;
}
// 加载历史数据
async loadHistory(startTime, endTime) {
this.historyData = await this.dataSource.query({
start: startTime,
end: endTime,
metrics: ['pm25', 'temp', 'humidity']
});
this.currentTime = startTime;
}
// 开始回放
play() {
this.isPlaying = true;
this.playbackLoop();
}
// 回放循环
playbackLoop() {
if (!this.isPlaying) return;
// 获取当前时间点的数据
const currentData = this.historyData.filter(
d => d.ts === this.currentTime
);
// 更新 3D 场景
currentData.forEach(data => {
this.renderer.updateObject(data);
});
// 更新时间轴 UI
this.updateTimeline(this.currentTime);
// 前进时间
this.currentTime += 30 * 1000 * this.playbackSpeed; // 30秒间隔
// 继续循环
setTimeout(() => this.playbackLoop(), 100); // 100ms 刷新率
}
}模块 | 功能 | 技术实现 |
|---|---|---|
场景加载 | 3D 模型加载、进度显示 | glTF Loader、Progress Bar |
空间导航 | 漫游、飞行、聚焦 | OrbitControls、FlyControls |
数据可视化 | 颜色映射、热力图、粒子 | ShaderMaterial、PointCloud |
交互操作 | 点击、框选、拖拽 | Raycaster、EventDispatcher |
信息展示 | 悬浮面板、详情窗口 | CSS2DRenderer、DOM Overlay |
历史回放 | 时间轴、播放控制 | Timeline、AnimationMixer |
告警展示 | 闪烁、声音、弹窗 | EffectComposer、AudioListener |
+-------------------------------------------------------+
| 标题栏:县档案馆 3F 空气质量监控系统 |
+-------------------------------------------------------+
| 工具栏:漫游 | 飞行 | 聚焦 | 测量 | 截图 | 全屏 |
+-------------------------------------------------------+
| |
| 3D 场景区域 |
| (可旋转、缩放、平移) |
| |
| [传感器图标] [密集架模型] [热力图叠加] |
| |
+-------------------------------------------------------+
| 信息面板: |
| - 当前选中:文书库A-01列-1.5m |
| - PM2.5: 45 μg/m³ (良) [趋势图] |
| - 温度: 21.3℃ [趋势图] |
| - 湿度: 52%RH [趋势图] |
| - 更新时间: 2026-09-18 14:30:00 |
+-------------------------------------------------------+
| 时间轴:=====|=====|=====|=====|=====|=====|===== |
| 08:00 10:00 12:00 14:00 16:00 18:00 |
| [播放] [暂停] [快进] [慢放] [循环] |
+-------------------------------------------------------+
| 告警栏:[2条未处理] PM2.5超标(文书库A-03列) 14:25 |
+-------------------------------------------------------+# 联动规则配置文件
rules:
# PM2.5 超标联动
- name: pm25_high_alarm
condition:
metric: pm25
operator: ">"
threshold: 75
duration: 300 # 持续5分钟
actions:
- type: 3d_highlight
target: space
color: 0xff9900
blink: true
- type: notification
channels: ["web", "wechat", "sms"]
level: warning
message: "库房{{space_id}} PM2.5超标:{{value}}μg/m³"
- type: device_control
target: "purifier_{{space_id}}"
command: "turn_on"
params: {mode: "high"}
- type: video_capture
target: "camera_{{space_id}}"
duration: 30
# 湿度高联动(防霉)
- name: humidity_high_mold_risk
condition:
metric: humidity
operator: ">"
threshold: 60
and:
metric: temp
operator: "between"
min: 18
max: 28
duration: 1800 # 持续30分钟
actions:
- type: 3d_highlight
target: space
color: 0xff6600
- type: notification
level: critical
message: "库房{{space_id}}霉变风险:湿度{{humidity}}%,温度{{temp}}℃"
- type: device_control
target: "dehumidifier_{{space_id}}"
command: "turn_on"
- type: log
content: "触发防霉联动:启动除湿机"
# 新装修区域甲醛联动
- name: formaldehyde_alarm
condition:
metric: formaldehyde
operator: ">"
threshold: 0.08 # mg/m³
actions:
- type: 3d_highlight
target: space
color: 0xff0000
blink: true
- type: notification
level: critical
channels: ["web", "wechat", "sms", "call"]
- type: device_control
target: "ventilation_{{space_id}}"
command: "turn_on"
params: {mode: "maximum"}
- type: access_control
target: "door_{{space_id}}"
command: "lock"
reason: "甲醛超标,禁止进入"1. 边缘网关检测到 PM2.5 = 82 μg/m³ (>75)
2. 持续 5 分钟确认(防误报)
3. 触发 pm25_high_alarm 规则
4. 事件总线广播告警事件
5. 3D 引擎响应:
a. 高亮对应空间区域(橙色闪烁)
b. 弹出告警信息面板
c. 自动聚焦到异常区域
d. 关联摄像头抓拍
6. 平台执行:
a. 发送微信/短信通知运维人员
b. 下发指令启动空气净化器
c. 记录告警日志和处置记录
7. 运维人员通过 3D 界面确认:
a. 查看实时数据和历史趋势
b. 检查净化器运行状态
c. 填写处置结果
8. PM2.5 降至 65 μg/m³ 后,自动解除告警
9. 3D 场景恢复正常显示类别 | 验收项 | 验收标准 | 结果 |
|---|---|---|---|
数据接入 | 传感器在线率 | ≥ 99% | ✅ |
数据更新频率 | ≤ 30 秒 | ✅ | |
数据准确性 | 与手持仪表误差 ≤ 5% | ✅ | |
3D 可视化 | 模型加载时间 | ≤ 5 秒 | ✅ |
帧率 | ≥ 30 fps | ✅ | |
交互响应 | ≤ 200 ms | ✅ | |
联动功能 | 告警响应时间 | ≤ 3 秒 | ✅ |
联动准确率 | ≥ 95% | ✅ | |
控制成功率 | ≥ 99% | ✅ | |
业务功能 | 八防覆盖 | 防尘、防污染、防潮 | ✅ |
历史数据查询 | 支持日/周/月/年 | ✅ | |
报表导出 | 支持 Excel/PDF | ✅ | |
安全审计 | 操作日志 | 100% 记录 | ✅ |
数据完整性 | 断网恢复不丢数 | ✅ | |
权限控制 | 分级授权 | ✅ |
从平面到孪生,不是技术的堆砌,而是以档案安全为中心,以业务需求为导向,以数据驱动为基础,以 3D 可视化为手段的系统工程。
当管理员在 3D 场景中看到:
这时,智慧档案库房才真正实现了“看得见、管得住、防得早、查得清”。
标签:#智慧档案馆建设#档案馆温湿度监控系统#档案八防系统#档案十防系统#档案恒温恒湿系统#数字孪生#3D可视化#空气质量监测
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。