智能插座能耗监控与自愈脚本:防止 NAS 与服务器意外掉电

很多在家里搭建私有 NAS、家庭助理网关或本地 GPU 小主机的工程师,都遇到过令人心碎的"家庭意外断电":
老妈打扫卫生时顺手把插排的总开关关了;或者家里电水壶短路跳闸;甚至某些廉价的智能插座因为 Wi-Fi 偶发离线误触发了默认继电器关闭,导致正在写入数据的 NAS 磁盘阵列异常掉电,RAID 校验直接报警。
家用服务器不像企业机房拥有双路市电和发电机,必须在有限的预算内,构建一套基于智能插座能耗遥测 + 离线自愈 + UPS 软联动的被动防御系统。
flowchart TD
AC[市电输入] –> UPS[小型家用后备 UPS 600VA]
UPS –> SmartPlug[带功率计量的 Zigbee/MQTT 智能插座]
SmartPlug –> NAS[家庭私有 NAS / Mini-PC 节点]
SmartPlug -.->|实时 MQTT 功率上报| Watchdog[本地 Watchdog 守护进程]
Watchdog –>|市电中断/功率归零| ShutdownFlow[触发 NUT 优雅关机流水线\\n(卸载文件系统/安全刷盘停机)]
Watchdog –>|继电器异常关闭| AutoRecover[硬编码互锁: 5秒内强制重开继电器]
智能插座防误关的"固件级互锁"
在选择家庭服务器专用智能插座时,必须遵守两条红线:
基于 Python 的能耗监控与服务器守护自愈脚本
以下是在软路由或本地守护容器中运行的实时看门狗代码:
import paho.mqtt.client as mqtt
import json
import time
import subprocess
import os
MQTT_BROKER = "192.168.20.5"
MQTT_PORT = 1883
TOPIC_POWER_TELEMETRY = "zigbee2mqtt/server_plug"
TOPIC_PLUG_COMMAND = "zigbee2mqtt/server_plug/set"
class ServerPowerWatchdog:
def __init__(self):
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.last_power_w = 0.0
self.last_seen_time = time.time()
def on_connect(self, client, userdata, flags, rc, properties=None):
print("已连接至家庭 MQTT 遥测总线,监听服务器插座功率…")
client.subscribe(TOPIC_POWER_TELEMETRY)
def on_message(self, client, userdata, msg):
try:
payload = json.loads(msg.payload.decode())
state = payload.get("state", "OFF")
power_w = float(payload.get("power", 0.0))
self.last_power_w = power_w
self.last_seen_time = time.time()
# 1. 自愈防御:若检测到继电器非预期被关闭,立刻下发强制开启指令
if state == "OFF":
print("🚨 警告:检测到服务器插座被误触关闭!正在下发强制恢复通电指令…")
self.client.publish(TOPIC_PLUG_COMMAND, json.dumps({"state": "ON"}), qos=2)
self._send_wechat_alert("【紧急】服务器插座被意外关闭,系统已在 1 秒内自愈重新通电!")
# 2. 功耗骤降异动告警 (服务器正常待机约 25W,若持续低于 5W 提示可能死机)
elif power_w < 5.0 and state == "ON":
print(f"⚠️ 提示:服务器功耗异常偏低 ({power_w}W),可能处于关机或内核死锁状态")
except Exception as e:
print(f"解析 MQTT 报文异常: {e}")
def _send_wechat_alert(self, content: str):
# 调用家庭 Bot 发送企业微信/通知渠道
pass
def run(self):
self.client.connect(MQTT_BROKER, MQTT_PORT, 60)
self.client.loop_forever()
if __name__ == "__main__":
watchdog = ServerPowerWatchdog()
watchdog.run()
NUT (Network UPS Tools) 优雅关机防丢数据
如果遭遇大范围真正停电,UPS 电池将在 15 分钟后耗尽。此时必须通过开源的 NUT 服务执行自动化优雅关机:
# /etc/nut/upsmon.conf 核心安全策略
MONITOR ups@localhost 1 monuser mysecretpassword slave
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POWERDOWNFLAG /etc/killpower
# 当 UPS 电量跌破 20% 时触发全盘同步刷盘并卸载 ZFS/Btrfs 文件系统
NOTIFYCMD /usr/local/bin/safe_unmount_nas.sh
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
物理底座的敬畏心
软件的世界里有无数次 git revert 和 Ctrl+Z 的后悔药,但物理世界的电压与磁盘一旦断电损毁,付出的是珍贵家庭照片和数据资产的永久灭失。
用一套严谨自愈的本地监控守护脚本、一台安静的后备 UPS,把每一次意外都牢牢化解在毫秒级的反应之间,这便是居家工程师给自己最大的确定感。


