1. 项目概述实时温度监控系统能做什么最近在整理工作室的设备发现一个挺有意思的需求我有一台常年开机的NAS服务器还有几台用来跑渲染和编译的工控机一到夏天机箱风扇就呼呼作响跟直升机起飞似的。我总担心哪天哪个核心部件过热直接罢工把辛苦跑了几天几夜的数据给毁了。光靠手摸机箱或者偶尔看一眼BIOS里的温度心里实在没底。于是我就琢磨着能不能自己搭一套“Realtime temperature monitor”——实时温度监控系统。说白了这东西的核心目标就一个持续、自动地采集关键设备的温度数据并以一种直观、即时的方式展示出来一旦温度异常能立刻通知我。它解决的痛点非常明确对于需要7x24小时稳定运行的设备比如家庭服务器、树莓派集群、3D打印机、甚至是你精心打造的鱼缸或温室大棚温度是衡量其健康状态和运行环境的最基础、也最关键的指标之一。过热可能导致硬件永久损坏、性能降级或者像我担心的那样数据丢失。这个项目听起来有点硬核但实际上它的技术栈非常灵活可以做得极简也可以非常复杂。你可以用一块几块钱的传感器加一个单片机在本地小屏幕上显示也可以像我一样用树莓派或任何Linux小主机搭配Python脚本把数据扔到云端数据库再做个漂亮的网页看板随时随地用手机查看。它适合任何对“状态监控”有需求的爱好者、创客或者像我这样有点“设备焦虑症”的运维人员。无论你是想监控电脑CPU温度、房间温湿度还是某个特定实验环境的温度变化这套思路都是相通的。接下来我就把我搭建这套系统的完整思路、踩过的坑和最终方案毫无保留地分享出来。2. 系统核心架构与设计选型搭建一个实时监控系统首先得想清楚它的骨架怎么搭。你不能拿到传感器就开干那样很容易做成一团乱麻后期加功能或者排查问题会非常痛苦。我的设计核心是“数据流水线”思想采集 - 处理 - 存储 - 展示 - 告警每个环节相对独立通过标准接口比如网络API、消息队列连接。2.1 硬件选型传感器是眼睛温度传感器的选择是第一步它决定了数据的源头质量。市面上常见的有这几类DS18B20这是我最初的选择也是很多入门项目的首选。它是数字传感器单总线协议一根数据线就能挂多个抗干扰能力不错精度在±0.5°C完全够用。最大的优点是便宜、皮实、接口简单。缺点是读取速度相对慢一点750ms最大但对我们这种秒级甚至分钟级采集的场景忽略不计。DHT22 (AM2302)这是一个温湿度复合传感器。如果你需要同时监控湿度比如机房、温室它是一个性价比很高的选择。它是数字输出但协议比较特殊需要微控制器有精确的时序控制能力。精度温度±0.5°C湿度±2%RH。BME280这是“进阶版”的环境传感器能测温度、湿度、气压。I2C或SPI接口精度高体积小但价格也贵一些。如果你需要更全面的环境数据或者项目对精度有要求选它。主板/CPU内置传感器对于监控电脑本身我们根本不需要外接传感器。在Linux下lm-sensors包可以轻松读取CPU、主板、硬盘通过hddtemp的温度。在Windows下也有Open Hardware Monitor这样的库可以通过WMI或直接读取内存地址获取数据。我的选择与理由由于我主要监控的是机箱内部空气温度和个别硬盘的表面温度对湿度要求不高且希望布线简单一根线串多个传感器所以我选择了DS18B20。它的单总线特性让我用一根GPIO口就能连接多个传感器分别贴在机箱进气口、出风口和硬盘架上成本极低。对于电脑本身的CPU温度则通过软件直接获取。注意DS18B20有TO-92封装像三极管和防水探头封装。机箱内使用TO-92即可如果需要测量液体或恶劣环境务必选择防水探头版并做好线缆的防护。2.2 软件架构让数据流动起来硬件确定了软件怎么组织我放弃了那种一个脚本把所有事都干完的“意大利面条式”代码采用了分层架构数据采集层 (Agent)这是跑在被监控设备上的轻量级程序。它的唯一职责就是以固定的时间间隔如每10秒读取传感器的值。我用Python写因为它有丰富的硬件库如RPi.GPIO用于树莓派读取DS18B20psutil用于获取系统温度和网络请求库。这一层代码要尽可能简单、健壮具备基本的本地日志和错误重试机制。数据传输层采集到的数据怎么送到中心服务器有多种方案HTTP POST最简单直接采集Agent将数据打包成JSON通过HTTP请求发送到中心服务器的某个API接口。适合内网环境实现简单。MQTT这是一个轻量级的发布/订阅消息协议。采集Agent作为发布者Publisher将温度数据发布到特定的主题如sensors/room/temperature中心服务器作为订阅者Subscriber接收消息。这是我强烈推荐的方案。它的优势在于解耦、低带宽、适合物联网场景。即使中心服务器短暂离线Agent端也可以配置保留消息等服务器恢复后重传。直接写入数据库如果Agent和数据库服务器在同一可信网络也可以直接用数据库驱动如pymysqlfor MySQL,psycopg2for PostgreSQL写入。但这将Agent与数据库耦合不够灵活。数据存储层时间序列数据随时间变化的数据点有其特殊性写多读少数据按时间顺序到达。使用传统的关系型数据库如MySQL虽然也能存但效率不高且查询时间范围数据时比较麻烦。时间序列数据库 (TSDB)是为此而生的。我选择了InfluxDB原因如下专门为时间序列数据优化写入和查询速度极快。数据模型简单直观measurement类似表如temperature,tags索引字段如sensor_id“cpu”, location“server_room”,fields数值字段如value45.6,timestamp。自带强大的数据聚合和连续查询功能方便做数据降采样比如把每秒的数据聚合成每分钟的平均值存储节省空间。数据展示与告警层存起来的数据要能看得见出了问题要能叫得应。展示我使用Grafana。它是一款开源的可视化工具支持多种数据源包括InfluxDB。你可以轻松地创建包含曲线图、仪表盘、数字面板等组件的看板自定义刷新频率做出非常专业的监控界面。告警Grafana本身也具备告警功能可以设置规则如“当CPU温度连续5分钟超过80°C时”并通过多种渠道通知如邮件、钉钉、企业微信、Slack等。你也可以在数据写入层如Telegraf InfluxDB的数据采集器或处理层设置告警。最终架构图文字描述树莓派运行Python采集Agent- MQTT Broker (Mosquitto) - 处理脚本订阅MQTT写入InfluxDB- InfluxDB (存储) - Grafana (查询并展示设置告警)。电脑主机则运行一个轻量级Agent直接通过HTTP或MQTT上报系统传感器数据。3. 核心模块实现与实操细节理论说完了我们进入实战环节。我会以最经典的“树莓派 DS18B20 MQTT InfluxDB Grafana”组合为例拆解每一步。3.1 硬件连接与系统配置首先把DS18B20传感器接到树莓派上。接线非常简单DS18B20的VDD(红线) 接树莓派的3.3V引脚。DS18B20的GND(黑线) 接树莓派的GND。DS18B20的DQ(数据线通常是黄线或白线) 接树莓派的某个GPIO引脚例如GPIO4(物理引脚7)。为了稳定信号通常需要在数据线和3.3V之间加一个4.7kΩ的上拉电阻。很多传感器模块已经集成了这个电阻购买时留意一下。接线完成后登录树莓派需要启用单总线1-Wire接口。sudo raspi-config选择Interface Options-1-Wire-Yes启用。重启后如果连接正确传感器会被系统识别。你可以通过以下命令检查ls /sys/bus/w1/devices/你应该能看到一个以28-开头的文件夹如28-00000xxxxxxx这就是你的传感器ID。3.2 数据采集Agent编写Python这是核心代码之一它的稳定性直接决定了数据流的源头是否可靠。#!/usr/bin/env python3 import time import json import paho.mqtt.client as mqtt import RPi.GPIO as GPIO import os import logging # 配置日志方便排查问题 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) # MQTT配置 MQTT_BROKER 192.168.1.100 # 你的MQTT服务器IP MQTT_PORT 1883 MQTT_TOPIC_TEMP sensors/temperature # 设备标识用于区分不同来源的数据 DEVICE_ID raspberrypi_room # DS18B20读取函数 def read_ds18b20(sensor_id): 读取指定ID的DS18B20传感器温度值 try: sensor_file f/sys/bus/w1/devices/{sensor_id}/w1_slave if not os.path.exists(sensor_file): logger.error(f传感器文件 {sensor_file} 不存在) return None with open(sensor_file, r) as f: lines f.readlines() # 检查数据是否有效 if lines[0].strip()[-3:] ! YES: logger.warning(f传感器 {sensor_id} CRC校验失败) return None # 解析温度值 equals_pos lines[1].find(t) if equals_pos ! -1: temp_string lines[1][equals_pos2:] temp_c float(temp_string) / 1000.0 return round(temp_c, 2) # 保留两位小数 else: return None except Exception as e: logger.exception(f读取传感器 {sensor_id} 时发生异常: {e}) return None # 发现并初始化传感器 def init_sensors(): 查找所有连接的DS18B20传感器 base_dir /sys/bus/w1/devices/ sensor_ids [] try: # 列出所有设备筛选出28开头的DS18B20 for device_folder in os.listdir(base_dir): if device_folder.startswith(28-): sensor_ids.append(device_folder) logger.info(f发现传感器: {device_folder}) except FileNotFoundError: logger.error(1-Wire总线未启用或路径不存在请检查raspi-config设置。) return sensor_ids # MQTT客户端连接回调 def on_connect(client, userdata, flags, rc): if rc 0: logger.info(成功连接到MQTT Broker) else: logger.error(f连接失败返回码: {rc}) def main(): # 初始化传感器列表 sensor_list init_sensors() if not sensor_list: logger.error(未找到任何DS18B20传感器程序退出。) return # 设置MQTT客户端 client mqtt.Client(client_idDEVICE_ID) client.on_connect on_connect client.username_pw_set(username, password) # 如果MQTT服务器需要认证 try: client.connect(MQTT_BROKER, MQTT_PORT, 60) client.loop_start() # 启动网络循环线程 except Exception as e: logger.error(f无法连接到MQTT Broker: {e}) return logger.info(开始采集温度数据...) try: while True: payload_list [] timestamp int(time.time() * 1000) # 毫秒级时间戳InfluxDB推荐 for sensor_id in sensor_list: temp read_ds18b20(sensor_id) if temp is not None: # 构建每条传感器数据 sensor_data { measurement: temperature, tags: { device: DEVICE_ID, sensor_id: sensor_id, location: server_room # 根据实际位置修改 }, fields: { value: temp }, time: timestamp } payload_list.append(sensor_data) else: logger.warning(f传感器 {sensor_id} 读数无效本次跳过。) # 将本次读取的所有传感器数据一起发送减少MQTT消息数量 if payload_list: try: # 发布JSON格式的数据 client.publish(MQTT_TOPIC_TEMP, json.dumps(payload_list), qos1) # QoS 1确保至少送达一次 logger.debug(f已发布数据: {payload_list}) except Exception as e: logger.error(fMQTT发布失败: {e}) # 每10秒采集一次 time.sleep(10) except KeyboardInterrupt: logger.info(程序被用户中断) finally: client.loop_stop() client.disconnect() logger.info(MQTT连接已断开) if __name__ __main__: main()关键点解析与避坑指南错误处理与日志采集端必须健壮。代码中包含了文件是否存在、CRC校验、网络异常等处理并通过logging模块记录不同级别日志。生产环境建议将日志写入文件 (logging.FileHandler) 并设置日志轮转方便后续排查。MQTT QoS代码中设置了qos1。QoS服务质量等级0是“至多一次”可能丢失1是“至少一次”确保送达但可能重复2是“恰好一次”开销大。对于温度监控QoS 1是性价比最高的选择能有效避免因网络波动导致的数据丢失。数据打包我选择将一次循环中所有传感器的读数打包成一个JSON数组发送而不是每个传感器发一条消息。这显著减少了MQTT Broker的连接压力和网络流量尤其是在传感器较多时。时间戳使用统一的毫秒级时间戳 (int(time.time() * 1000))并放在应用层数据里。这比依赖MQTT消息到达时间更准确尤其是在Agent和服务器时间不同步时。3.3 MQTT Broker搭建与数据桥接采集端把数据发到MQTT主题了我们需要一个Broker来接收并有一个“桥接”程序把数据从MQTT写入InfluxDB。安装Mosquitto (MQTT Broker):sudo apt update sudo apt install mosquitto mosquitto-clients sudo systemctl enable mosquitto sudo systemctl start mosquitto默认配置已足够内网使用。如果需要认证可以修改/etc/mosquitto/mosquitto.conf设置密码文件。编写数据桥接脚本 (MQTT - InfluxDB):这个脚本订阅MQTT主题收到数据后解析并写入InfluxDB。我同样用Python实现。#!/usr/bin/env python3 import json import paho.mqtt.client as mqtt from influxdb import InfluxDBClient import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) # 配置 MQTT_BROKER localhost # 假设和本脚本在同一台机器 MQTT_PORT 1883 MQTT_TOPIC sensors/temperature INFLUXDB_HOST localhost INFLUXDB_PORT 8086 INFLUXDB_DATABASE temperature_monitor # InfluxDB 2.x 以下版本使用用户名密码2.x以上使用token INFLUXDB_USER admin INFLUXDB_PASSWORD your_password # 连接InfluxDB try: influx_client InfluxDBClient( hostINFLUXDB_HOST, portINFLUXDB_PORT, usernameINFLUXDB_USER, passwordINFLUXDB_PASSWORD, databaseINFLUXDB_DATABASE ) # 创建数据库如果不存在 influx_client.create_database(INFLUXDB_DATABASE) logger.info(f已连接到InfluxDB: {INFLUXDB_DATABASE}) except Exception as e: logger.error(f连接InfluxDB失败: {e}) exit(1) # MQTT消息处理回调 def on_message(client, userdata, msg): try: payload msg.payload.decode(utf-8) data_points json.loads(payload) if isinstance(data_points, list): # 写入InfluxDB if influx_client.write_points(data_points): logger.debug(f成功写入 {len(data_points)} 个数据点到InfluxDB) else: logger.error(写入InfluxDB失败) else: logger.warning(f收到非列表格式的MQTT消息: {payload}) except json.JSONDecodeError as e: logger.error(fMQTT消息JSON解析失败: {e}, 原始数据: {msg.payload}) except Exception as e: logger.exception(f处理MQTT消息时发生未知错误: {e}) def main(): client mqtt.Client() client.on_message on_message try: client.connect(MQTT_BROKER, MQTT_PORT, 60) client.subscribe(MQTT_TOPIC, qos1) # 同样使用QoS 1 logger.info(f已订阅主题: {MQTT_TOPIC}) client.loop_forever() # 阻塞式循环持续监听 except KeyboardInterrupt: logger.info(桥接服务停止) except Exception as e: logger.error(fMQTT连接或订阅失败: {e}) finally: client.disconnect() influx_client.close() if __name__ __main__: main()将这个脚本设置为系统服务让它开机自启并在崩溃后重启保证桥接的稳定性。创建一个systemd服务文件/etc/systemd/system/temp_mqtt_bridge.service:[Unit] DescriptionTemperature MQTT to InfluxDB Bridge Afternetwork.target mosquitto.service influxdb.service Wantsmosquitto.service influxdb.service [Service] Typesimple Userpi WorkingDirectory/home/pi/temp_monitor ExecStart/usr/bin/python3 /home/pi/temp_monitor/mqtt_bridge.py Restarton-failure RestartSec10 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target然后启用服务sudo systemctl enable --now temp_mqtt_bridge.service3.4 InfluxDB安装与配置InfluxDB的安装很简单以在Ubuntu/Debian或树莓派上为例# 添加InfluxData仓库 wget -q https://repos.influxdata.com/influxdata-archive.key sudo gpg --dearmor -o /usr/share/keyrings/influxdata-archive-keyring.gpg echo deb [signed-by/usr/share/keyrings/influxdata-archive-keyring.gpg] https://repos.influxdata.com/debian stable main | sudo tee /etc/apt/sources.list.d/influxdata.list sudo apt update sudo apt install influxdb2 sudo systemctl enable influxdb sudo systemctl start influxdb安装完成后访问http://你的服务器IP:8086进行初始设置创建组织、存储桶Bucket相当于数据库、并生成一个All-Access Token令牌这个令牌在后面的桥接脚本和Grafana中会用到。对于InfluxDB 2.x上面的桥接脚本需要稍作修改使用新的influxdb-client库和Token认证方式from influxdb_client import InfluxDBClient, Point, WritePrecision from influxdb_client.client.write_api import SYNCHRONOUS token 你的All-Access Token org 你的组织名 bucket 你的存储桶名 client InfluxDBClient(urlhttp://localhost:8086, tokentoken) write_api client.write_api(write_optionsSYNCHRONOUS) # 在on_message函数中构建InfluxDB 2.x的Point对象并写入 for data in data_points: p Point(temperature) \ .tag(device, data[tags][device]) \ .tag(sensor_id, data[tags][sensor_id]) \ .tag(location, data[tags][location]) \ .field(value, data[fields][value]) \ .time(data[time], WritePrecision.MS) write_api.write(bucketbucket, orgorg, recordp)3.5 Grafana看板配置这是最有成就感的一步让数据“活”起来。安装Grafanasudo apt-get install -y software-properties-common sudo add-apt-repository deb https://packages.grafana.com/oss/deb stable main wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add - sudo apt-get update sudo apt-get install grafana sudo systemctl enable grafana-server sudo systemctl start grafana-server访问与登录浏览器打开http://服务器IP:3000默认账号密码admin/admin首次登录会要求修改。添加数据源左侧菜单Configuration-Data Sources-Add data source选择InfluxDB。Query Language: 选择 FluxInfluxDB 2.x推荐或 InfluxQL1.x。URL:http://localhost:8086(如果Grafana和InfluxDB在同一台机器)。认证在InfluxDB Details中填入你的Organization、Token和Default Bucket。 点击Save Test显示成功即可。创建仪表盘左侧菜单Create-Dashboard-Add new panel。数据查询在面板编辑器中选择刚添加的InfluxDB数据源。使用Flux语言查询例如from(bucket: temperature_monitor) | range(start: -1h) // 查询最近1小时数据 | filter(fn: (r) r._measurement temperature) | filter(fn: (r) r._field value) | filter(fn: (r) r.location server_room) // 按标签筛选 | aggregateWindow(every: 1m, fn: mean) // 每分钟聚合一次取平均值可视化设置在右侧Visualization选择Time series时间序列图。你可以在Panel options中设置标题在Axis中设置Y轴标签为“温度(°C)”在Legend中设置显示模式。添加多个查询一个面板可以叠加多条曲线。点击Query标签页的 Query可以添加另一个传感器的查询比如过滤条件换成r.sensor_id “28-xxxxxxx”就能在同一个图上对比不同位置的温度。设置告警在面板编辑界面切换到Alert标签页。Create alert rule from this panel。设置规则Rule name填“CPU温度过高”。在Query部分确保你的查询返回的是需要监控的指标比如CPU温度。条件Reduce函数选择last()(取最新值)Input选择A(你的查询)Threshold选择is above值设为80。评估频率Evaluate every设为1mFor设为5m意思是每1分钟检查一次如果连续5分钟都超过80°C则触发告警。通知渠道点击Add contact point可以配置邮件、钉钉等。需要先在Alerting-Contact points中设置好通知渠道。至此一个完整的、从硬件传感器到可视化看板的实时温度监控系统就搭建完成了。你可以复制采集Agent到多台设备只需修改DEVICE_ID和传感器位置标签就能轻松扩展监控范围。4. 常见问题、优化与深度扩展在实际部署和运行中你肯定会遇到各种问题。下面是我踩过的一些坑和对应的解决方案以及一些让系统更可靠的优化思路。4.1 典型问题排查清单问题现象可能原因排查步骤Grafana图表无数据1. 数据源连接失败2. 查询语句错误3. 数据根本没写入InfluxDB1. 检查Grafana数据源配置Save Test是否成功。2. 在Grafana的Explore功能中手动执行查询看是否有返回。3. 登录InfluxDB命令行或UI查看对应Bucket中是否有数据。检查桥接脚本日志。MQTT消息丢失1. 网络不稳定2. Broker压力大或崩溃3. QoS设置过低1. 使用mosquitto_sub命令订阅主题测试Agent发布的消息是否能被收到。2. 检查Broker资源占用CPU、内存和日志。3. 将Agent和桥接脚本的QoS都设为1。传感器读数异常如-127°C或85°C1. 接线松动或电源不稳2. 传感器损坏3. 上拉电阻未接或阻值不对1. 重新插拔接线确保接触良好电源电压稳定在3.3V。2. 更换传感器测试。3. 确认4.7kΩ上拉电阻已正确连接在数据线和3.3V之间。采集Agent进程莫名退出1. Python依赖缺失或版本冲突2. 未捕获的异常导致崩溃3. 系统资源不足1. 检查日志文件看退出前是否有错误信息。使用pip list确认paho-mqtt等库已安装。2. 在代码中使用try...except包裹主循环记录所有异常。3. 将Agent配置为系统服务如systemd并设置Restarton-failure。数据延迟高1. 采集间隔设置过长2. 网络延迟或阻塞3. InfluxDB写入性能瓶颈1. 适当缩短采集间隔如从10秒改为5秒。2. 检查网络状况确保MQTT Broker和InfluxDB服务器网络通畅。3. 监控InfluxDB的写入性能对于海量数据每秒数千点可能需要调整InfluxDB配置或使用更强大的硬件。4.2 系统优化与进阶玩法基础系统跑起来后可以考虑以下优化来提升其可靠性、功能和美观度使用Telegraf替代自定义桥接脚本InfluxDB官方提供的采集代理Telegraf功能极其强大。它内置了MQTT消费者插件 (inputs.mqtt_consumer) 和无数其他输入/输出插件。你可以用Telegraf直接订阅MQTT主题解析JSON数据并写入InfluxDB无需自己写Python桥接脚本。配置更统一管理也更方便。# telegraf.conf 片段 [[inputs.mqtt_consumer]] servers [tcp://localhost:1883] topics [sensors/temperature] data_format json json_time_key time json_time_format unix_ms tag_keys [device, sensor_id, location] json_string_fields [] json_name_key measurement [[outputs.influxdb_v2]] urls [http://localhost:8086] token $INFLUX_TOKEN organization your_org bucket temperature_monitor数据降采样与保留策略原始秒级数据会占用大量存储空间。可以在InfluxDB中创建连续查询(Continuous Query, CQ)或使用Flux任务自动将高频数据聚合成低频数据如将每秒数据聚合成每小时平均值并存入另一个Bucket。同时为原始数据和聚合数据设置不同的保留策略(Retention Policy, RP)比如原始数据保留7天聚合数据保留1年。这能有效控制数据库体积。Grafana看板美化与模板化变量Variables在Dashboard设置里添加变量比如$sensor值通过查询InfluxDB的tag值获得。然后在每个图表的查询中用r.sensor_id “$sensor”来过滤。这样你就能通过一个下拉菜单动态切换查看不同传感器的图表。统计面板除了曲线图多用用Stat统计和Gauge仪表盘可视化类型。在Dashboard首页放几个大的仪表盘显示当前各关键点的实时温度一目了然。告警面板创建一个专门的面板使用Alert list可视化类型集中展示当前触发的告警方便集中处理。监控系统自身别忘了监控你的监控系统为运行Agent、Broker、InfluxDB、Grafana的服务器本身也添加基础监控CPU、内存、磁盘确保监控系统健康运行。这可以通过Telegraf的inputs.system插件轻松实现。容器化部署如果你熟悉Docker可以将MQTT Broker (Eclipse Mosquitto)、InfluxDB、Grafana、Telegraf全部容器化用docker-compose.yml统一管理。这极大简化了部署和迁移流程环境隔离也更好。version: 3.8 services: influxdb: image: influxdb:2.7 container_name: influxdb ports: - 8086:8086 volumes: - ./influxdb2:/var/lib/influxdb2 environment: - DOCKER_INFLUXDB_INIT_MODEsetup - DOCKER_INFLUXDB_INIT_USERNAMEadmin - DOCKER_INFLUXDB_INIT_PASSWORDyour_secure_password - DOCKER_INFLUXDB_INIT_ORGmyorg - DOCKER_INFLUXDB_INIT_BUCKETmybucket - DOCKER_INFLUXDB_INIT_ADMIN_TOKENmy-super-secret-auth-token grafana: image: grafana/grafana:latest container_name: grafana ports: - 3000:3000 volumes: - ./grafana_data:/var/lib/grafana depends_on: - influxdb telegraf: image: telegraf:latest container_name: telegraf volumes: - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro depends_on: - influxdb mosquitto: image: eclipse-mosquitto:latest container_name: mosquitto ports: - 1883:1883 - 9001:9001 # WebSocket端口可选 volumes: - ./mosquitto/config:/mosquitto/config - ./mosquitto/data:/mosquitto/data - ./mosquitto/log:/mosquitto/log这个实时温度监控项目就像搭积木每个模块都有清晰的接口和替代方案。你可以根据自身需求和技术栈灵活替换其中任何一环。比如把树莓派换成ESP32把InfluxDB换成TimescaleDB基于PostgreSQL的时间序列数据库把Grafana换成自研的简单网页。核心在于理解“数据流水线”的思想。一旦这套系统稳定运行你获得的将不仅仅是几个温度数字而是一种对设备运行状态“了如指掌”的掌控感和安全感。当手机突然收到告警推送你就能在问题扩大之前及时干预这或许就是技术带给生活最实在的价值。