用 Mosquitto MQTT + CurrentCost 电表 + Asterisk 实现“烤箱预热完成自动提醒“:一个完整的家庭自动化实战
发布时间:2026/9/27 21:18:25来源:尧图网络
物联网消息队列后端【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址https://gitcode.com/gh_mirrors/mosquit/mosquitto点击查看免费下载导读本文基于 Mosquitto 官方博客 2010 年 6 月发布的经典实践文章《Automation: Has the oven warmed up yet?》完整还原一个真实可运行的家庭自动化方案用 CurrentCost CC128 电力监测仪采集家庭用电数据通过 Mosquitto MQTT broker 进行消息流转再借助 Asterisk 电话系统在烤箱预热完成时自动打电话提醒主人。读者读完本文后可以掌握传感器数据采集 → MQTT 消息发布/订阅 → 事件判定 → 电话通知这一完整的 IoT 自动化链路并能在 Mosquitto 仓库的 misc/currentcost 目录中找到全部配套脚本。问题背景烤箱预热是被忽视的能源浪费英国 BBC 科普节目《Bang Goes the Theory》有一期名为 The Human Power Station 的节目让一个四口之家的全部电力由一群骑行发电的志愿者供应以此揭示日常生活中被大量浪费的能源。节目中一个典型案例就是烤晚餐烤箱被提前打开预热食谱的第一条指令往往就是预热烤箱但实际上要过很久才会真正使用大量电能就这样白白消耗掉了。更常见的场景是把冷冻食品放进烤箱前需要预热人们常常先打开烤箱预热开关然后转身去忙别的事情最后忘记检查烤箱是否已经预热完成。这篇 2010 年的文章作者也遇到过同样的问题而他的解决方案非常优雅——不直接测量烤箱本身而是通过监控整户用电功率的间接证据来判断烤箱状态并把烤箱已预热这一事件通过电话语音通知出来。整个系统由三个开源/商用组件构成组件作用CurrentCost CC128 电力监测仪采集家庭总用电功率Mosquitto MQTT broker承载传感器数据的发布/订阅消息流转Asterisk 电话交换机提供电话触发监控、电话语音通知方案总览从用电功率下降到电话通知整套系统的数据流可以概括为一条清晰的管道采集CC128 电表通过串口把 XML 格式的用电读数发送给一台低功耗 Linux 电脑入站cc128_read.py 或 cc128_read.pl 读取串口数据发布到 Mosquitto broker 的sensors/cc128/raw主题解析cc128_parse.pl 订阅原始主题把 XML 解析成Unix 时间戳 功率的友好格式重新发布到sensors/cc128/ch1主题判定oven_monitor.pl持续监听功率数据当功率跌破设定阈值约 2kW时判定烤箱预热完成退出并执行oven_warmed_up.sh通知oven_warmed_up.sh把oven.call文件放入 Asterisk 的外呼目录/var/spool/asterisk/outgoing/触发一次电话呼叫播放烤箱已预热语音。其中第 13 步的脚本在 Mosquitto 仓库的 misc/currentcost 目录中完整保留可以直接阅读与复用第 45 步的oven_monitor.pl、oven_warmed_up.sh、oven.call三个文件当时随博客以附件形式发布原始链接指向/files/examples/oven-asterisk/在当前的仓库快照中未收录下文将依据博客原文描述其行为逻辑。第一步采集电力数据并发布到 MQTT串口读取与原始数据发布CC128 电表通过串口输出数据。仓库中的两个脚本提供了 Python 与 Perl 两种实现cc128_read.pyPython 实现#!/usr/bin/python -u import mosquitto import serial usb serial.Serial(port/dev/ttyUSB0, baudrate57600) mosq mosquitto.Mosquitto() mosq.connect(localhost) mosq.loop_start() running True try: while running: line usb.readline() mosq.publish(sensors/cc128/raw, line) except usb.SerialException, e: running False mosq.disconnect() mosq.loop_stop()cc128_read.plPerl 实现#!/usr/bin/perl -w use strict; use Device::SerialPort qw( :PARAM :STAT 0.07 ); my $pubclient mosquitto_pub -t sensors/cc128/raw -q 1 -l; my $PORT /dev/ttyUSB0; local $| 1; my $ob Device::SerialPort-new($PORT); $ob-baudrate(57600); $ob-write_settings; open(SERIAL, $PORT); open(MQTT, |$pubclient); while (my $line SERIAL) { print(MQTT $line); } close(MQTT);两个脚本的关键点完全一致串口参数设备节点为/dev/ttyUSB0USB 转串口适配器波特率 57600原始主题sensors/cc128/raw数据以每行一条 XML 消息的形式逐行发布Python 版直接使用mosquittoPython 客户端库连接本机 broker注意这是当时最早的 Python 绑定如今已演化为 Paho MQTT Python 客户端接口有差异Perl 版通过管道把数据喂给mosquitto_pub命令其中-l参数是关键——它让mosquitto_pub以逐行读取 stdin、每行作为一条独立消息发布的模式工作。这一行为在官方手册 man/mosquitto_pub.1.xml 中有明确记载手册中甚至直接给出了与本文场景一致的示例Send parsed electricity usage data from a Current Cost meter, reading from stdin with one line/reading as one message从 stdin 逐行读取已解析的 Current Cost 用电数据每行一条消息。解析并重新发布友好格式mosquitto_pub -l把原始行发布到sensors/cc128/raw后cc128_parse.pl 负责把 XML 解析成更容易被下游程序消费的纯文本格式#!/usr/bin/perl -w use strict; use HTTP::Date str2time; use FileHandle; local $| 1; my $subclient mosquitto_sub -t sensors/cc128/raw -q 1; my $pubclient mosquitto_pub -t sensors/cc128 -q 1 -l; my $pubclient_ch1 mosquitto_pub -t sensors/cc128/ch1 -q 1 -l; open(SUB, $subclient|); open(PUB, |$pubclient); open(PUB_CH1, |$pubclient_ch1); SUB-autoflush(1); PUB-autoflush(1); PUB_CH1-autoflush(1); while (my $line SUB) { #msgsrcCC128-v0.12/srcdsb00002/dsbtime00:02:12/timetmpr15.7/tmprsensor0/sensorid03112/idtype1/typech1watts00108/watts/ch1/msg if ($line ~ m#time(.*)/timetmpr *([\-\d.])/tmprsensor0/sensorid[0-9]*/idtype1/typech1watts0*(\d)/watts/ch1/msg.*#){ my $reading_time $1; my $temp $2; my $watts $3; my $now time; my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst,$r_stamp); ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) localtime($now); $year 1900; $month 1; $r_stamp str2time($year-$month-$mday $reading_time); if($r_stamp $now){ $r_stamp - 86400; } print PUB $r_stamp,$temp,$watts\n; print PUB_CH1 $r_stamp $watts\n; } }这个脚本体现了几个值得借鉴的设计订阅原始主题通过mosquitto_sub -t sensors/cc128/raw -q 1订阅原始数据QoS 1管道逐行送入解析循环XML 正则解析CC128 的输出形如msgsrcCC128-v0.12/src...time00:02:12/timetmpr15.7/tmpr...ch1watts00108/watts/ch1/msg脚本用正则一次性提取时间、温度℃和通道 1 的功率瓦并去掉 watts 字段的前导零时间戳修正电表只给当天时刻如 00:02:12脚本用str2time拼出完整时间戳若解析出的时间晚于当前时间则减去一天86400 秒正确处理跨午夜场景双主题发布sensors/cc128输出Unix时间戳,温度,功率三条数据供 MySQL 日志等通用消费sensors/cc128/ch1输出Unix时间戳 功率两条数据供烤箱判定这类纯功率应用使用。仓库中还有一个配套脚本 cc128_log_mysql.pl演示了如何订阅sensors/cc128主题并把数据写入 MySQL 数据库做长期归档其注释中给出了建库、建表、建用户的完整 SQL可作为本方案的扩展参考。第二步用功率阈值判定烤箱预热完成由于作者家使用的是电烤箱烤箱加热器开启时整户用电功率约为2.4kW。因此判定逻辑非常简单当用电功率跌破这个数值时说明烤箱加热器已经关闭即烤箱预热完成。博客原文中实现这一判定的脚本是oven_monitor.pl其行为为持续监听功率数据当用电功率跌破 2kW 时运行oven_warmed_up.sh然后退出。注意原文对 2.4kW 与 2kW 两个数值均有提及——2.4kW 是烤箱加热时的典型功率2kW 是脚本中实际使用的触发阈值留出了 0.4kW 的判定余量。作者也坦承这一判定方式略微简单化它测的是整户用电而非烤箱单独用电。如果恰好在烤箱预热期间同时打开电水壶等大功率电器功率读数就可能短暂跌破阈值造成误判。这一局限只有在 CurrentCost 推出单电器监测配件后才能彻底解决。这个间接测量 阈值判定的思路正是 MQTT 物联网架构的典型应用传感器电表与执行器电话通知之间完全解耦中间只靠 broker 上的主题消息连接任何一方都可以独立更换或扩展。第三步用 Asterisk 电话系统触发监控与通知为什么用电话触发监控由于间接测量存在误判风险作者不希望监控脚本 7×24 小时常驻运行否则电水壶等设备启动也可能触发烤箱预热完成的假通知。正确做法是只在真正打开烤箱时启动监控。作者的家用电话是 Siemens C460IP——一款普通座机 IP 电话二合一设备而 Asterisk 恰好运行在与 Mosquitto 同一台服务器上于是电话系统成了最自然的触发与控制入口。新增分机 100呼叫即启动监控在 Asterisk 拨号方案中新增分机 100拨通后依次执行接听 → 后台启动监控脚本 → 播放提示音 → 挂断exten 100,1,Answer() exten 100,n,System(echo /usr/local/bin/oven_pub.pl | at now) exten 100,n,Playback(oven-trigger) exten 100,n,Hangup各步含义Answer()接听来电System(echo /usr/local/bin/oven_pub.pl | at now)通过at命令把监控脚本放入后台立即执行。作者特意说明使用at而不是直接调用脚本是为了避免阻塞 Asterisk 的拨号流程——at是 Linux 下把任务放入后台排队执行的简单方法Playback(oven-trigger)播放名为oven-trigger的语音提示让拨号的人知道监控已经启动Hangup挂断。这里提到的脚本是oven_pub.pl原始博客正文引用的链接为oven_monitor.pl二者在文中交替出现指的都是同一套监控触发脚本。呼叫分机 100 之后烤箱预热完成与否就交给后台脚本去盯了。预热完成自动拨打你的电话监控脚本oven_monitor.pl检测到功率跌破阈值后执行oven_warmed_up.sh并退出。最终一步的反馈动作发生在oven_warmed_up.sh中脚本再次调用 Asterisk发起一通到座机的出站呼叫出站呼叫的实现方式是把oven.call文件移动复制到/var/spool/asterisk/outgoing/目录——这是 Asterisk 的标准外呼机制Asterisk 会监视该目录发现新的 .call 文件即按文件内容发起呼叫电话接通后播放提示语音告诉主人烤箱已经预热好了。至此从打开烤箱、拨个电话到烤箱预热完成、接到电话提醒的自动化闭环就完成了。方案的局限与改进方向作者在文末坦诚列出了这套方案的已知局限并邀请读者提出改进建议无法区分具体电器整户电表的功率读数无法确认功率来自烤箱还是其他设备如电水壶同时开启会造成误判只能等待 CurrentCost 的单电器监测配件阈值依赖烤箱类型2.4kW 是作者家特定电烤箱的典型功率燃气烤箱或其他功率规格的电烤箱需要重新标定阈值触发依赖人工必须主动拨号分机 100 才启动监控尚未做到检测到烤箱开启自动开始监控例如可以通过功率从待机值跃升到 2.4kW 的上升沿自动触发。从仓库源码看这套方案的扩展空间是开放的sensors/cc128与sensors/cc128/ch1主题上的数据可以被任意数量的订阅者消费比如 cc128_log_mysql.pl 负责持久化归档、google-powermeter-step-by-step.md 展示了把同一份数据转发到 Google PowerMeter 做可视化而本文则用同一份数据驱动电话通知——这正是 MQTT 发布/订阅模型一份数据、多方消费的经典价值体现。结语2010 年的 MQTT 家庭自动化蓝图回顾这篇 2010 年的实践文章它几乎完整勾勒出了今天智能家居系统的标准范式物理传感器CurrentCost CC128→ 边缘网关采集串口脚本→ MQTT broker 消息中枢Mosquitto→ 业务判定逻辑阈值脚本→ 用户触达电话语音。整个系统全部由开源组件构成、数据链路清晰、各环节可独立替换即使放在今天依然是一份高质量的 MQTT 入门到实战教材。对于想要复现的读者仓库中的 misc/currentcost 目录提供了现成的采集与解析脚本配合一个 MQTT broker 和任意消息消费者就能重建从电表读数到事件通知的完整管道。赞分享物联网消息队列后端【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址https://gitcode.com/gh_mirrors/mosquit/mosquitto点击查看免费下载相关推荐用 Mosquitto MQTT 与 Asterisk 实现烤箱预热完成提醒基于 CurrentCost 电表数据的家庭自动化实践用 Mosquitto MQTT 与 Asterisk 实现烤箱预热完成提醒基于 CurrentCost 电表数据的家庭自动化实践 导读 本文还原并深度解析物联网消息队列后端网络/通信用 Mosquitto MQTT 与 Asterisk 构建烤箱预热完成电话提醒系统一个 2010 年的家庭自动化实战用 Mosquitto MQTT 与 Asterisk 构建烤箱预热完成电话提醒系统一个 2010 年的家庭自动化实战 本文是 Eclipse Mosqu后端消息队列消息路由基于 Mosquitto 的智能电表数据上报方案CurrentCost MQTT MySQL Google Powermeter 实战指南基于 Mosquitto 的智能电表数据上报方案CurrentCost MQTT MySQL Google Powermeter 实战指南 本文整物联网消息队列后端网络/通信上一篇SVG图片优化与内联Nuxt Optimized Images高级用法指南下一篇Mojo编译器原理从源码到机器码的魔法转换过程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网