ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于小米智能插座与Python实现家庭设备用电监控与自动断电方案

基于小米智能插座与Python实现家庭设备用电监控与自动断电方案 1. 项目缘起从“电费刺客”到智能管家上个月交电费的时候我又被账单吓了一跳。家里那台老旧的台式电脑明明只是待机一个月下来竟然悄无声息地“偷”走了几十度电。类似的情况还有路由器、机顶盒、充电器长期插着不拔……这些“电费刺客”无处不在积少成多一年下来也是一笔不小的开支。手动去拔插头太麻烦也容易忘于是我就琢磨着能不能让设备自己“聪明”起来在不需要用电的时候自动断电手头正好有几个闲置的小米智能插座它本身就能通过手机App远程开关。但远程控制还是需要我手动操作算不上真正的“智能”。我的目标是实现自动化让插座能实时监控接入设备的耗电情况并根据我设定的规则比如待机功率超过阈值、夜间特定时段等自动执行断电操作。这听起来像是需要复杂的硬件改造或者自己写个服务器程序但其实利用现有的生态和开源工具完全可以在不写一行服务器代码的情况下搭建一个低成本、高可用的家庭用电智能监控与自动化系统。这个项目就是围绕这个核心需求展开的。2. 核心组件选型与工作原理拆解要实现监控与自动断电我们需要几个核心部分数据采集器、逻辑处理器和执行器。在这个项目中它们分别对应着具体的软硬件。2.1 硬件基石小米智能插座Wi-Fi版我选用的是小米米家智能插座Wi-Fi版型号ZNCZ04CM。选择它的理由很充分内置电量统计模块这是最关键的功能。它不仅能开关还能实时测量并上报电压、电流、功率和累计用电量。数据精度对于家庭监控完全足够。开放的本地通信协议小米智能家居设备大多支持miIO或miot协议。这意味着我们可以不经过小米云服务器直接在家庭局域网内与设备通信获取数据和发送指令。这带来了响应速度快、断网可用、隐私可控三大好处。广泛的可用性价格亲民生态成熟相关的开源解决方案多。它的工作原理是插座内部集成了计量芯片持续测量负载回路的电气参数。这些数据通过设备的Wi-Fi模块按照一定的协议格式封装既可以上报到小米云供官方App显示也可以响应来自局域网的特定查询请求。2.2 软件桥梁Python python-miio 库这是整个项目的“大脑”和“神经”。我们通过在家庭网络中的一台常开设备比如一台旧电脑、树莓派、甚至是安装了终端模拟器App的旧手机上运行Python脚本来扮演逻辑控制中心的角色。python-miio库这是一个第三方开源库它实现了与小米智能设备包括插座、网关、空气净化器等的本地通信协议。我们可以用它来发现设备、查询状态包括实时功率、发送控制命令开/关。为什么选Python生态好python-miio库成熟稳定语法简单易于实现业务逻辑比如“如果功率5瓦超过10分钟则执行关闭”跨平台可以在Windows、Linux、macOS甚至一些嵌入式系统上运行。2.3 自动化框架系统原生任务计划 vs. 第三方工具逻辑脚本需要定时或持续运行。这里有几种方案Linux (树莓派)使用cron定时任务每分钟执行一次脚本检查。Windows使用“任务计划程序”同样可以设置每分钟触发。更优雅的方案如果设备支持在树莓派上使用systemd服务将脚本作为守护进程运行实现7x24小时监控。对于需要复杂定时或跨设备联动的场景可以集成到Home Assistant这类开源家庭自动化平台中利用其强大的UI和自动化引擎。本项目先从简单的cron方案入手。整个系统的工作流可以概括为插座计量 - 本地网络查询 - Python脚本分析 - 脚本决策 - 本地网络发送指令 - 插座执行。全程数据不出局域网响应在秒级以内。3. 实战部署从零搭建监控与自动化系统下面我将以在树莓派Raspberry Pi OS系统上部署为例手把手走通全流程。如果你用Windows或Mac思路一致只是安装命令和任务计划设置方式不同。3.1 环境准备与依赖安装首先确保你的树莓派已经连接到家庭Wi-Fi并且和智能插座在同一个局域网内。更新系统并安装Python3及pip树莓派OS通常已预装但建议更新到最新。sudo apt update sudo apt upgrade -y sudo apt install python3-pip -y安装核心python-miio库pip3 install python-miio这个命令会安装miio命令行工具及其Python库。3.2 发现设备并获取通信令牌Token这是最关键也是最容易卡住的一步。我们需要知道插座的IP地址和通信令牌。查找IP地址进入你家路由器的管理后台通常地址是192.168.1.1或192.168.31.1在“已连接设备”或“DHCP客户端列表”中找到设备名类似“chuangmi.plug”或“ZNCZ04CM”的设备记下其分配的IP地址。假设为192.168.31.100。获取Token令牌这是设备本地通信的密码。有几种方法这里介绍较通用的一种需配合安卓手机或模拟器在安卓手机上从官方应用商店安装“米家”App并登录账号。将智能插座绑定到你的米家账号下。在电脑上下载并安装安卓模拟器如BlueStacks在模拟器中安装“米家”App并使用同一个账号登录。在模拟器的米家App中找到该智能插座进入插件详情页。使用模拟器内的文件管理器或通过ADB命令定位到米家App的数据目录。通常路径为/data/data/com.xiaomi.smarthome/databases/找到名为miio2.db的数据库文件将其拷贝到电脑上。使用SQLite数据库查看工具如DB Browser for SQLite打开这个文件。查找名为devicerecord的表其中token字段的十六进制字符串形如a1b2c3d4e5f678901234567890123456就是该设备的令牌。请妥善保管此Token不要泄露。注意获取Token的过程因小米App版本和加密方式更新可能失效。如果上述方法不行可以搜索“小米智能插座 token 获取”查找最新的教程有些开源工具如miio命令的discover模式在特定条件下也可能辅助获取。这是整个项目最大的“坑点”。3.3 测试设备连接获取到IP和Token后我们先用命令行测试连通性。miio --ip 192.168.31.100 --token a1b2c3d4e5f678901234567890123456 info如果成功你会看到一长串JSON格式的设备信息包括型号、固件版本、网络信息等。这证明你的IP和Token是正确的可以正常通信。3.4 编写核心监控与自动化Python脚本接下来我们编写实现核心逻辑的脚本。创建一个文件例如power_monitor.py。#!/usr/bin/env python3 小米智能插座功率监控与自动断电脚本 import time import logging from miio import ChuangmiPlug # 配置日志方便查看运行情况 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) # 设备配置 PLUG_IP 192.168.31.100 PLUG_TOKEN a1b2c3d4e5f678901234567890123456 # 自动化规则参数 POWER_THRESHOLD 5.0 # 功率阈值单位瓦特。低于此值认为处于待机状态。 IDLE_TIME_LIMIT 600 # 待机时间限制单位秒。连续待机超过此时间则断电。 CHECK_INTERVAL 30 # 检查间隔单位秒。每隔多久检查一次功率。 class SmartPlugMonitor: def __init__(self, ip, token): 初始化插座连接 try: self.plug ChuangmiPlug(ip, token) # 首次连接获取一下状态测试连通性 status self.plug.status() logger.info(f成功连接到插座。当前状态: 开关{status.is_on}, 功率{status.power} W) self.is_connected True except Exception as e: logger.error(f连接插座失败: {e}) self.is_connected False self.idle_start_time None # 记录开始进入待机状态的时间 def get_current_power(self): 获取当前实时功率 if not self.is_connected: return None try: status self.plug.status() return status.power except Exception as e: logger.error(f获取功率失败: {e}) self.is_connected False return None def turn_off(self): 关闭插座 if not self.is_connected: return False try: self.plug.off() logger.info(执行断电操作。) self.idle_start_time None # 重置待机计时 return True except Exception as e: logger.error(f断电操作失败: {e}) return False def monitor_loop(self): 主监控循环 if not self.is_connected: logger.error(初始化连接失败监控循环退出。) return logger.info(f开始监控。规则功率{POWER_THRESHOLD}W持续{IDLE_TIME_LIMIT}秒后自动断电。) while True: current_power self.get_current_power() if current_power is None: # 获取功率失败等待后重试 time.sleep(CHECK_INTERVAL * 2) continue logger.debug(f当前功率: {current_power:.2f} W) if current_power POWER_THRESHOLD: # 进入低功耗待机状态 if self.idle_start_time is None: self.idle_start_time time.time() logger.info(f检测到低功耗状态({current_power:.2f}W)开始计时...) else: idle_duration time.time() - self.idle_start_time if idle_duration IDLE_TIME_LIMIT: logger.warning(f待机时间({idle_duration:.0f}秒)超过限制触发自动断电。) if self.turn_off(): # 断电后可以退出循环或等待下一次手动开启 logger.info(设备已断电监控任务暂停。如需重新监控请重启脚本。) break # 跳出循环任务结束。也可以选择不break持续监控。 else: # 断电失败重置计时避免连续失败日志刷屏 self.idle_start_time None else: # 还在待机计时中 pass else: # 功率正常重置待机计时器 if self.idle_start_time is not None: logger.info(f功率恢复({current_power:.2f}W)重置待机计时。) self.idle_start_time None # 等待下一个检查周期 time.sleep(CHECK_INTERVAL) if __name__ __main__: monitor SmartPlugMonitor(PLUG_IP, PLUG_TOKEN) monitor.monitor_loop()脚本逻辑解读初始化使用python-miio的ChuangmiPlug类连接插座。主循环每CHECK_INTERVAL秒例如30秒获取一次实时功率。状态判断如果功率低于POWER_THRESHOLD如5瓦则认为设备进入待机。首次进入待机时记录时间点idle_start_time。持续监测如果待机时长超过IDLE_TIME_LIMIT如600秒即10分钟则调用turn_off()方法断电。如果在计时期间功率恢复例如你又开始使用电脑则清零idle_start_time重新计时。执行与退出触发断电后脚本可以选择退出如示例也可以继续运行等待插座下次被手动或其它方式打开后继续监控。3.5 设置开机自启与后台运行为了让脚本在树莓派启动后自动运行我们将其配置为一个systemd服务。创建服务文件sudo nano /etc/systemd/system/power-monitor.service写入以下内容请修改ExecStart路径为你的脚本实际存放位置[Unit] DescriptionSmart Plug Power Monitor Service Afternetwork.target [Service] Typesimple Userpi # 替换为你的用户名如‘root’ WorkingDirectory/home/pi # 替换为脚本所在目录 ExecStart/usr/bin/python3 /home/pi/power_monitor.py Restarton-failure RestartSec10 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target启用并启动服务sudo systemctl daemon-reload sudo systemctl enable power-monitor.service sudo systemctl start power-monitor.service检查服务状态和日志sudo systemctl status power-monitor.service sudo journalctl -u power-monitor.service -f至此一个完整的、自动化的设备耗电监控与断电系统就部署完成了。你的树莓派会默默地在后台运行这个脚本守护你的插座。4. 进阶优化与场景扩展基础功能跑通后我们可以根据实际需求对这个系统进行多方面的增强。4.1 规则优化更智能的判断逻辑上面的脚本使用了简单的“低功率超时”规则。在实际应用中可能需要更复杂的策略分时段规则例如只在凌晨0点到早上6点执行待机断电规则白天则只监控不执行。import datetime current_hour datetime.datetime.now().hour if 0 current_hour 6: # 执行夜间断电规则 pass例外名单为某些特定设备设置保护。例如NAS需要24小时开机可以设置当设备名或功率特征符合时跳过自动断电逻辑。平滑处理功率可能存在瞬时波动。可以改为检查“最近N次采样的平均功率低于阈值”避免因瞬间波动误触发。power_readings [] # 用一个列表存储最近的功率读数 # ... 每次读取后加入列表 power_readings.append(current_power) if len(power_readings) 10: power_readings.pop(0) # 保持最近10次读数 avg_power sum(power_readings) / len(power_readings) # 使用 avg_power 进行判断4.2 状态通知与可视化单纯的断电缺乏反馈。我们可以增加通知功能邮件/短信通知在断电前或断电后通过smtplib库发送邮件到自己的邮箱。App推送集成Bark、PushDeer、Server酱等免费推送服务在手机上接收通知。本地日志聚合将日志写入文件并配合logrotate进行管理。甚至可以将功率数据写入SQLite或InfluxDB数据库然后用Grafana绘制漂亮的用电曲线图直观查看设备用电习惯和历史。4.3 集成到家庭自动化中枢Home Assistant如果你已经在使用Home AssistantHA那么实现这个功能会更容易且能获得强大的UI和跨设备联动能力。在HA中集成小米插座通过Xiaomi Miot Auto或Xiaomi Gateway 3等集成将插座接入HA。这一步通常只需要扫码或输入账号比获取Token简单。利用HA传感器接入后插座在HA中会成为一个switch实体并自带current_power当前功率传感器。创建自动化在HA的“自动化”编辑器中使用可视化界面或YAML代码创建规则。# 示例HA自动化YAML alias: Auto Turn Off Plug on Low Power description: 当插座功率低于5瓦超过10分钟时关闭它 trigger: - platform: state entity_id: sensor.plug_power # 替换为你的功率传感器实体ID for: hours: 0 minutes: 10 seconds: 0 to: 5 condition: [] action: - service: switch.turn_off target: entity_id: switch.plug # 替换为你的插座开关实体ID mode: single这种方式无需编写Python脚本利用HA的稳定引擎可靠性高且能与家中其他传感器如人体存在传感器、门窗传感器联动实现更复杂的场景如“人离开书房且电脑待机则断电”。4.4 多设备管理与集中控制如果你有多个小米插座可以对上面的Python脚本进行改造用一个脚本管理所有设备。创建一个设备列表在主循环中遍历每个插座进行检查和操作。甚至可以设计一个简单的Web界面用Flask等轻量级框架通过浏览器查看所有插座的实时状态和手动控制。5. 避坑指南与经验心得在折腾这个项目的过程中我踩过不少坑也总结了一些经验。5.1 关于Token获取的稳定性Token获取是最大难点。小米会不定期更新App的加密和数据库存储方式导致旧方法失效。经验优先尝试从安卓米家App的数据库提取。如果不行关注python-miio项目的GitHub页面和Issues社区经常会有新方法讨论。有些特定型号的插座在特定旧版固件下可能可以通过miio discover命令在抓包辅助下获取。最一劳永逸的方法是在首次将设备绑定到米家App时就使用一些开源工具如miio命令的--sync模式需在绑定瞬间抓包来截获Token。但这需要一定的技术能力。5.2 网络稳定性与设备掉线Wi-Fi设备可能因为网络波动而暂时失联。脚本容错我们的脚本中已经有了基本的重试机制获取功率失败后等待更长时间。可以进一步加强比如连续失败N次后尝试重新初始化ChuangmiPlug对象。设备端确保插座所在位置的Wi-Fi信号良好。如果条件允许将智能家居设备连接到专用的IoT Wi-Fi网络2.4GHz并与主网络隔离可以提高稳定性。5.3 功率阈值的校准“待机功率”阈值需要根据具体设备来设定。实测法先让设备进入你认为是“待机”的状态如电脑睡眠、电视关机但插头未拔运行脚本并观察日志中报告的功率值取一个略高于该值的数作为阈值。我的台式电脑睡眠后功率约2-3瓦所以我设5瓦而一些老式机顶盒关机后可能还有7-8瓦阈值就需要设到10瓦左右。5.4 自动化规则的“误伤”规则设计不当可能导致误操作。例如你正在下载大文件瞬时网速慢导致CPU使用率低功率短暂下降如果检查间隔太短可能误判为待机。心得“宽进严出”。即“进入待机判断可以快一点但执行断电一定要慢一点”。可以通过延长IDLE_TIME_LIMIT比如15-30分钟或者使用前面提到的平均功率算法来大幅减少误判。对于重要设备宁可它多费一点电也不要错误断电导致工作中断或数据丢失。5.5 长期运行的维护脚本作为服务长期运行需要考虑日志轮转、异常自恢复等问题。使用systemd的优势我们之前配置的systemd服务其中的Restarton-failure和RestartSec10参数可以确保脚本因异常退出后自动重启。日志管理journalctl默认会管理日志大小。你也可以在服务文件中配置StandardOutput和StandardError重定向到特定的日志文件并配合logrotate进行切割和清理避免磁盘被写满。这个项目本质上是一个典型的IoT物联网应用场景感知功率- 分析规则判断- 执行控制。它没有复杂的算法但非常实用。通过它你不仅省了电费更深入理解了智能设备本地通信、自动化脚本编写和系统服务部署的完整链条。当你看到脚本按照预定逻辑在深夜自动关掉那些“偷电”的设备时那种“机器听话了”的成就感才是DIY智能家居最大的乐趣。
返回列表