zigbee2mqtt地理围栏:基于位置的家庭自动化触发
引言:位置感知的家庭自动化痛点与解决方案
你是否曾经历过这样的场景:下班回家走到门口,屋内灯光却没有自动亮起;或是假期外出,忘记关闭家中的空调导致能源浪费?传统的家庭自动化系统往往依赖于固定的时间触发或手动操作,无法根据家庭成员的实时位置智能调整。zigbee2mqtt作为一款强大的Zigbee到MQTT协议转换工具,虽然本身不直接提供地理围栏(Geofence)功能,但通过与外部系统的集成,我们可以构建一套灵活的基于位置的自动化触发机制。
本文将详细介绍如何利用zigbee2mqtt结合主流智能家居平台和定位技术,实现精准的地理围栏家庭自动化。读完本文后,你将能够:
- 理解地理围栏在家庭自动化中的应用场景与工作原理
- 搭建基于zigbee2mqtt的位置感知自动化系统架构
- 配置跨平台的设备位置数据采集方案
- 编写基于位置的自动化规则与脚本
- 优化地理围栏触发的准确性与响应速度
地理围栏自动化的系统架构设计
核心组件与数据流
基于zigbee2mqtt实现地理围栏功能需要整合多个组件,形成完整的位置感知闭环。以下是系统的核心构成部分及其交互流程:
表:系统核心组件说明
| 组件 | 功能描述 | 推荐方案 | 数据接口 |
|---|---|---|---|
| 用户位置源 | 提供家庭成员实时位置信息 | 智能手机(Android/iOS)、智能手表 | GPS坐标、区域标识符 |
| 位置处理服务 | 解析位置数据并生成地理围栏事件 | Home Assistant、Node-RED | MQTT主题发布(zigbee2mqtt/geofence/#) |
| MQTT Broker | 消息中转枢纽 | zigbee2mqtt内置Broker或Mosquitto | MQTT 3.1.1/5.0协议 |
| 自动化规则引擎 | 根据位置事件执行预设动作 | zigbee2mqtt规则引擎、外部自动化平台 | JSON格式控制指令 |
| Zigbee设备 | 执行物理操作的终端设备 | 智能开关、门锁、照明系统 | Zigbee Cluster Library规范 |
位置判定逻辑
地理围栏的核心在于准确判断用户是否进入或离开特定区域。系统采用多层次判定机制:
-
初级判定:基于经纬度坐标的距离计算
- 计算公式:Haversine公式(地球球面距离计算)
- 触发阈值:默认50米半径(可配置)
-
次级判定:结合网络环境辅助验证
- Wi-Fi网络检测(家庭Wi-Fi连接状态)
- 蓝牙信标识别(如存在家庭iBeacon设备)
-
状态平滑:防止位置抖动导致的误触发
- 进入延迟:持续30秒处于目标区域内才触发
- 离开延迟:离开区域后60秒未返回才触发
系统部署与配置步骤
前置条件与环境准备
硬件要求:
- 运行zigbee2mqtt的服务器(推荐至少1GB RAM)
- 支持MQTT协议的智能移动设备(Android 8.0+/iOS 12.0+)
- Zigbee协调器(如CC2531, CC2652P等)
- 至少一个Zigbee终端设备(如智能灯泡或插座)
软件版本:
- zigbee2mqtt v1.33.0+ (确保支持外部扩展)
- Node.js v18.16.0+ (如需运行自定义脚本)
- 移动设备定位应用(如OwnTracks, GPSLogger等)
位置数据采集配置
1. 移动设备配置(以OwnTracks为例)
OwnTracks是一款开源的位置追踪应用,支持将位置数据直接发送到MQTT broker:
配置步骤:
- 在手机上安装OwnTracks应用
- 进入应用设置 → 连接 → MQTT服务器
- 填写服务器信息:
- 服务器地址:
your-zigbee2mqtt-ip - 端口:
1883(或8883用于TLS加密) - 用户名/密码:与zigbee2mqtt相同的认证信息
- 客户端ID:
owntracks_<username>
- 服务器地址:
- 位置报告设置:
- 报告间隔:120秒(静止时),30秒(移动时)
- 距离阈值:20米(位置变化超过此距离才报告)
- 连接模式:MQTT持久连接
配置验证: 在zigbee2mqtt服务器上执行以下命令监控位置消息:
mosquitto_sub -h localhost -p 1883 -u your_username -P your_password -t "owntracks/#"
成功连接后应能看到类似JSON消息:
{
"_type": "location",
"acc": 20,
"alt": 35,
"batt": 87,
"conn": "w",
"lat": 39.9042,
"lon": 116.4074,
"t": "p",
"tid": "js",
"tst": 1693987200,
"vac": 3,
"vel": 0
}
2. MQTT消息转发配置
如果zigbee2mqtt与位置采集服务使用不同的MQTT broker,需要配置消息转发规则。编辑configuration.yaml文件:
mqtt:
base_topic: zigbee2mqtt
server: 'mqtt://localhost:1883'
user: your_username
password: your_password
# 位置消息转发规则
forward:
- from: 'owntracks/+/+'
to: 'zigbee2mqtt/geofence/owntracks/+'
qos: 1
retain: false
地理围栏区域定义
在zigbee2mqtt中定义地理围栏区域,编辑data/geofences.yaml文件:
# 家庭主围栏
home:
name: "我的家"
latitude: 39.9042 # 中心点纬度
longitude: 116.4074 # 中心点经度
radius: 50 # 围栏半径(米)
description: "住宅区域主围栏"
# 网络辅助验证
network_verification:
wifi_ssids: ["MyHomeWiFi", "MyHomeWiFi_5G"]
bluetooth_beacons:
- uuid: "123e4567-e89b-12d3-a456-426614174000"
major: 1
minor: 1
# 工作区域围栏(可选)
work:
name: "公司"
latitude: 39.9975
longitude: 116.3376
radius: 100
description: "工作区域围栏"
network_verification:
enabled: false # 禁用网络验证
自动化规则配置示例
基础场景:基于位置的照明控制
编辑zigbee2mqtt的自动化规则文件data/automations.yaml:
- id: geofence_lighting_control
alias: "地理围栏照明控制"
description: "当家庭成员到家时自动开灯,离家后关闭"
trigger:
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "home"
id: "arrived_home"
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "away"
id: "left_home"
condition:
- condition: time
after: "17:00"
before: "06:00"
alias: "仅在傍晚到凌晨之间触发"
action:
- choose:
- conditions:
- condition: trigger
id: "arrived_home"
sequence:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/living_room_main_light/set"
payload: '{"state": "ON", "brightness": 255}'
- delay: "00:00:05" # 延迟5秒
- service: mqtt.publish
data:
topic: "zigbee2mqtt/entrance_light/set"
payload: '{"state": "ON"}'
- conditions:
- condition: trigger
id: "left_home"
sequence:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/#/set"
payload: '{"state": "OFF"}'
except:
- "zigbee2mqtt/security_camera" # 排除监控摄像头
- "zigbee2mqtt/refrigerator" # 排除冰箱等必要设备
mode: queued
max: 10
高级场景:多用户位置协同
当家庭中有多位成员时,需要根据最后一个离开/第一个到达的逻辑触发自动化:
// 文件: data/scripts/geofence_coordinator.js
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://localhost:1883', {
username: 'your_username',
password: 'your_password'
});
// 存储家庭成员位置状态
const familyMembers = {
'dad': 'away', // 初始状态
'mom': 'away',
'kid1': 'away'
};
// 监听所有家庭成员的位置更新
client.subscribe('zigbee2mqtt/geofence/members/+/state');
client.on('message', (topic, message) => {
const member = topic.split('/')[3]; // 从主题提取成员ID
const newState = message.toString();
if (familyMembers[member] !== newState) {
familyMembers[member] = newState;
updateHomeState();
}
});
// 更新整体家居状态
function updateHomeState() {
const allAway = Object.values(familyMembers).every(state => state === 'away');
const someoneHome = Object.values(familyMembers).some(state => state === 'home');
let homeState;
if (allAway) {
homeState = 'away';
} else if (someoneHome) {
homeState = 'home';
}
if (homeState) {
client.publish(
'zigbee2mqtt/geofence/state',
homeState,
{ qos: 1, retain: true }
);
// 记录状态变更日志
console.log(`[${new Date().toISOString()}] Home state changed to: ${homeState}`);
}
}
设备集成与场景示例
常见设备类型的自动化配置
表:不同Zigbee设备的地理围栏触发配置
| 设备类型 | 在家模式 | 离家模式 | 特殊条件 | MQTT命令示例 |
|---|---|---|---|---|
| 智能照明 | 自动开启(亮度255) | 全部关闭 | 傍晚/夜间自动开灯 | {"state": "ON", "brightness": 255} |
| 恒温系统 | 设置24°C | 设置节能模式(18°C) | 冬季/夏季温度调整 | {"current_heating_setpoint": 24} |
| 智能门锁 | 保持解锁 | 自动上锁 | 最后一人离家时 | {"lock": "LOCK"} |
| 窗帘电机 | 打开50% | 完全关闭 | 白天/黑夜差异 | {"position": 50} |
| 安全摄像头 | 仅移动检测 | 持续录制 | 有人在家时禁用警报 | {"recording_mode": "motion"} |
| 智能插座 | 开启(电视/电脑) | 关闭(非必要设备) | 保留冰箱等必要设备 | {"state": "OFF"} |
典型场景实现方案
场景一:回家迎接模式
当检测到家庭成员进入地理围栏后,自动执行一系列迎接动作:
配置文件示例:
# 回家迎接模式自动化规则
- id: geofence_welcome_mode
alias: "回家迎接模式"
trigger:
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "home"
action:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/front_door_lock/set"
payload: '{"lock": "UNLOCK"}'
- delay: "00:00:02"
- service: mqtt.publish
data:
topic: "zigbee2mqtt/entrance_light/set"
payload: '{"state": "ON", "brightness": 255, "transition": 2}'
- service: mqtt.publish
data:
topic: "zigbee2mqtt/living_room_ac/set"
payload: >
{% if now().month >= 12 or now().month <= 2 %}
{"mode": "heat", "current_heating_setpoint": 22}
{% elif now().month >= 6 and now().month <= 8 %}
{"mode": "cool", "current_heating_setpoint": 26}
{% else %}
{"mode": "auto"}
{% endif %}
- service: mqtt.publish
data:
topic: "zigbee2mqtt/welcome_speaker/set"
payload: '{"state": "ON", "volume": 30, "track": "welcome.mp3"}'
场景二:离家安全模式
当最后一位家庭成员离开地理围栏后,系统自动进入全面安全模式:
- id: geofence_security_mode
alias: "离家安全模式"
trigger:
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "away"
action:
# 关闭所有灯光
- service: mqtt.publish
data:
topic: "zigbee2mqtt/#/set"
payload: '{"state": "OFF"}'
except:
- "zigbee2mqtt/security_camera"
# 锁好所有门窗
- service: mqtt.publish
data:
topic: "zigbee2mqtt/front_door_lock/set"
payload: '{"lock": "LOCK"}'
- service: mqtt.publish
data:
topic: "zigbee2mqtt/back_door_lock/set"
payload: '{"lock": "LOCK"}'
# 开启安全系统
- service: mqtt.publish
data:
topic: "zigbee2mqtt/security_system/set"
payload: '{"armed_mode": "armed_away"}'
# 关闭非必要电器
- service: mqtt.publish
data:
topic: "zigbee2mqtt/living_room_tv/set"
payload: '{"state": "OFF"}'
- service: mqtt.publish
data:
topic: "zigbee2mqtt/desktop_computer/set"
payload: '{"state": "OFF"}'
# 调整温控系统到节能模式
- service: mqtt.publish
data:
topic: "zigbee2mqtt/thermostat/set"
payload: >
{% if now().month >= 12 or now().month <= 2 %}
{"current_heating_setpoint": 18}
{% elif now().month >= 6 and now().month <= 8 %}
{"current_heating_setpoint": 28}
{% else %}
{"mode": "off"}
{% endif %}
高级功能与优化技巧
位置数据的隐私保护
地理围栏功能涉及用户位置隐私,需要采取适当的保护措施:
-
数据本地化处理
- 位置数据在本地网络内处理,不上传至云端
- 配置示例:
# 在OwnTracks中启用端到端加密 encryption: enabled: true key: "your-encryption-key-here" # 16/24/32字节的AES密钥
-
数据最小化原则
- 仅收集必要的位置数据
- 设置合理的位置报告间隔(如5分钟一次)
- 离家后降低位置更新频率
-
访问控制机制
- 为MQTT消息设置严格的访问权限
- 使用MQTT 5.0的主题权限控制功能
系统性能优化
-
网络流量优化
- 使用MQTT的QoS=1确保消息可靠传输
- 采用二进制有效载荷(如Protocol Buffers)减少流量
- 示例代码:
// 使用Protocol Buffers编码位置数据 const protobuf = require('protobufjs'); const root = protobuf.loadSync('location.proto'); const LocationMessage = root.lookupType('LocationMessage'); const message = LocationMessage.create({ userId: 'dad', latitude: 39.9042, longitude: 116.4074, accuracy: 20, timestamp: Date.now() }); const buffer = LocationMessage.encode(message).finish(); client.publish('zigbee2mqtt/geofence/protobuf', buffer);
-
自动化规则执行效率
- 合并相似规则减少重复计算
- 使用规则优先级避免冲突
- 实现规则执行结果缓存
-
系统资源占用控制
- 限制位置处理脚本的CPU占用(如使用nice命令)
- 设置内存使用上限(防止内存泄漏)
- 定期重启长时间运行的进程
故障排除与问题解决
常见问题及解决方案:
| 问题现象 | 可能原因 | 解决方法 | 验证步骤 |
|---|---|---|---|
| 地理围栏不触发 | GPS信号弱 | 切换到Wi-Fi/蓝牙定位辅助 | 查看应用位置数据精度>10米 |
| 频繁误触发 | 位置在围栏边缘波动 | 增大围栏半径或调整延迟时间 | 修改radius参数为100米测试 |
| 自动化执行延迟 | MQTT消息堆积 | 优化规则引擎性能 | 监控broker消息队列长度 |
| 部分设备无响应 | 设备离线或信号差 | 检查Zigbee网络信号强度 | 通过zigbee2mqtt frontend查看设备状态 |
| 位置数据不同步 | 网络连接问题 | 检查MQTT连接状态和重连机制 | 查看MQTT客户端连接日志 |
诊断工具使用:
-
查看zigbee2mqtt日志:
# 实时监控日志 tail -f /path/to/zigbee2mqtt/data/log/zigbee2mqtt.log | grep -i geofence # 搜索错误信息 grep -i error /path/to/zigbee2mqtt/data/log/zigbee2mqtt.log -
测试MQTT消息流:
# 发布测试位置消息 mosquitto_pub -h localhost -u user -P pass -t "zigbee2mqtt/geofence/members/dad/state" -m "home" # 订阅状态主题 mosquitto_sub -h localhost -u user -P pass -t "zigbee2mqtt/geofence/#" -
验证自动化规则:
# 使用zigbee2mqtt自带的规则测试工具 node cli.js rule test geofence_lighting_control
总结与未来展望
地理围栏功能为zigbee2mqtt带来了基于位置的智能自动化能力,通过本文介绍的方案,你可以实现家庭成员位置与家庭设备的无缝联动。系统的核心优势在于:
- 灵活性:支持多种位置数据源和判定逻辑
- 可扩展性:通过MQTT协议轻松集成新设备和服务
- 隐私保护:本地处理位置数据,无需云端服务
- 易维护性:基于yaml配置文件,修改无需重启系统
功能扩展建议
未来可以从以下方向扩展地理围栏功能:
- 多区域支持:实现多个地理围栏(如工作区、学校、父母家)的差异化自动化
- 预测性触发:基于历史数据预测用户到达时间,提前启动设备
- 天气集成:结合天气预报调整回家后的环境设置
- 健康状态关联:根据家庭成员健康状态调整自动化行为
最佳实践总结
- 从简单开始:先实现基础的离家/回家触发,再逐步扩展复杂场景
- 充分测试:在正式使用前在不同时间段和位置条件下测试
- 渐进优化:根据实际使用情况微调参数,如围栏半径、延迟时间
- 文档记录:详细记录设备配置和自动化规则,便于问题排查
通过zigbee2mqtt的地理围栏功能,你的智能家居系统将真正实现"感知"用户需求,提供更加贴心和无感的自动化体验。随着技术的发展,位置感知将成为智能家居系统的核心能力之一,为用户创造更加便捷、舒适和安全的居住环境。
如果你觉得本文对你有帮助,请点赞👍、收藏⭐并关注我们,下期将带来"zigbee2mqtt高级自动化:基于AI的行为预测"的深度教程!<|FCResponseEnd|>```markdown
zigbee2mqtt地理围栏:基于位置的家庭自动化触发
引言:位置感知的家庭自动化痛点与解决方案
你是否曾经历过这样的场景:下班回家走到门口,屋内灯光却没有自动亮起;或是假期外出,忘记关闭家中的空调导致能源浪费?传统的家庭自动化系统往往依赖于固定的时间触发或手动操作,无法根据家庭成员的实时位置智能调整。zigbee2mqtt作为一款强大的Zigbee到MQTT协议转换工具,虽然本身不直接提供地理围栏(Geofence)功能,但通过与外部系统的集成,我们可以构建一套灵活的基于位置的自动化触发机制。
读完本文后,你将能够:
- 理解地理围栏在家庭自动化中的应用场景与工作原理
- 搭建基于zigbee2mqtt的位置感知自动化系统架构
- 配置跨平台的设备位置数据采集方案
- 编写基于位置的自动化规则与脚本
- 优化地理围栏触发的准确性与响应速度
地理围栏自动化的系统架构设计
核心组件与数据流
基于zigbee2mqtt实现地理围栏功能需要整合多个组件,形成完整的位置感知闭环。以下是系统的核心构成部分及其交互流程:
表:系统核心组件说明
| 组件 | 功能描述 | 推荐方案 | 数据接口 |
|---|---|---|---|
| 用户位置源 | 提供家庭成员实时位置信息 | 智能手机(Android/iOS)、智能手表 | GPS坐标、区域标识符 |
| 位置处理服务 | 解析位置数据并生成地理围栏事件 | Home Assistant、Node-RED | MQTT主题发布(zigbee2mqtt/geofence/#) |
| MQTT Broker | 消息中转枢纽 | zigbee2mqtt内置Broker或Mosquitto | MQTT 3.1.1/5.0协议 |
| 自动化规则引擎 | 根据位置事件执行预设动作 | zigbee2mqtt规则引擎、外部自动化平台 | JSON格式控制指令 |
| Zigbee设备 | 执行物理操作的终端设备 | 智能开关、门锁、照明系统 | Zigbee Cluster Library规范 |
位置判定逻辑
地理围栏的核心在于准确判断用户是否进入或离开特定区域。系统采用多层次判定机制:
-
初级判定:基于经纬度坐标的距离计算
- 计算公式:Haversine公式(地球球面距离计算)
- 触发阈值:默认50米半径(可配置)
-
次级判定:结合网络环境辅助验证
- Wi-Fi网络检测(家庭Wi-Fi连接状态)
- 蓝牙信标识别(如存在家庭iBeacon设备)
-
状态平滑:防止位置抖动导致的误触发
- 进入延迟:持续30秒处于目标区域内才触发
- 离开延迟:离开区域后60秒未返回才触发
系统部署与配置步骤
前置条件与环境准备
硬件要求:
- 运行zigbee2mqtt的服务器(推荐至少1GB RAM)
- 支持MQTT协议的智能移动设备(Android 8.0+/iOS 12.0+)
- Zigbee协调器(如CC2531, CC2652P等)
- 至少一个Zigbee终端设备(如智能灯泡或插座)
软件版本:
- zigbee2mqtt v1.33.0+ (确保支持外部扩展)
- Node.js v18.16.0+ (如需运行自定义脚本)
- 移动设备定位应用(如OwnTracks, GPSLogger等)
位置数据采集配置
1. 移动设备配置(以OwnTracks为例)
OwnTracks是一款开源的位置追踪应用,支持将位置数据直接发送到MQTT broker:
配置步骤:
- 在手机上安装OwnTracks应用
- 进入应用设置 → 连接 → MQTT服务器
- 填写服务器信息:
- 服务器地址:
your-zigbee2mqtt-ip - 端口:
1883(或8883用于TLS加密) - 用户名/密码:与zigbee2mqtt相同的认证信息
- 客户端ID:
owntracks_<username>
- 服务器地址:
- 位置报告设置:
- 报告间隔:120秒(静止时),30秒(移动时)
- 距离阈值:20米(位置变化超过此距离才报告)
配置验证: 在zigbee2mqtt服务器上执行以下命令监控位置消息:
mosquitto_sub -h localhost -p 1883 -u your_username -P your_password -t "owntracks/#"
成功连接后应能看到类似JSON消息:
{
"_type": "location",
"acc": 20,
"alt": 35,
"batt": 87,
"conn": "w",
"lat": 39.9042,
"lon": 116.4074,
"t": "p",
"tid": "js",
"tst": 1693987200,
"vac": 3,
"vel": 0
}
2. MQTT消息转发配置
如果zigbee2mqtt与位置采集服务使用不同的MQTT broker,需要配置消息转发规则。编辑configuration.yaml文件:
mqtt:
base_topic: zigbee2mqtt
server: 'mqtt://localhost:1883'
user: your_username
password: your_password
# 位置消息转发规则
forward:
- from: 'owntracks/+/+'
to: 'zigbee2mqtt/geofence/owntracks/+'
qos: 1
retain: false
地理围栏区域定义
在zigbee2mqtt中定义地理围栏区域,编辑data/geofences.yaml文件:
# 家庭主围栏
home:
name: "我的家"
latitude: 39.9042 # 中心点纬度
longitude: 116.4074 # 中心点经度
radius: 50 # 围栏半径(米)
description: "住宅区域主围栏"
# 网络辅助验证
network_verification:
wifi_ssids: ["MyHomeWiFi", "MyHomeWiFi_5G"]
bluetooth_beacons:
- uuid: "123e4567-e89b-12d3-a456-426614174000"
major: 1
minor: 1
自动化规则配置与场景实现
基础场景:基于位置的照明控制
编辑zigbee2mqtt的自动化规则文件data/automations.yaml:
- id: geofence_lighting_control
alias: "地理围栏照明控制"
description: "当家庭成员到家时自动开灯,离家后关闭"
trigger:
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "home"
id: "arrived_home"
- platform: mqtt
topic: "zigbee2mqtt/geofence/state"
payload: "away"
id: "left_home"
condition:
- condition: time
after: "17:00"
before: "06:00"
alias: "仅在傍晚到凌晨之间触发"
action:
- choose:
- conditions:
- condition: trigger
id: "arrived_home"
sequence:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/living_room_main_light/set"
payload: '{"state": "ON", "brightness": 255}'
- delay: "00:00:05" # 延迟5秒
- service: mqtt.publish
data:
topic: "zigbee2mqtt/entrance_light/set"
payload: '{"state": "ON"}'
- conditions:
- condition: trigger
id: "left_home"
sequence:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/#/set"
payload: '{"state": "OFF"}'
except:
- "zigbee2mqtt/security_camera" # 排除监控摄像头
- "zigbee2mqtt/refrigerator" # 排除冰箱等必要设备
mode: queued
max: 10
高级场景:多用户位置协同
当家庭中有多位成员时,需要根据最后一个离开/第一个到达的逻辑触发自动化:
// 文件: data/scripts/geofence_coordinator.js
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://localhost:1883', {
username: 'your_username',
password: 'your_password'
});
// 存储家庭成员位置状态
const familyMembers = {
'dad': 'away', // 初始状态
'mom': 'away',
'kid1': 'away'
};
// 监听所有家庭成员的位置更新
client.subscribe('zigbee2mqtt/geofence/members/+/state');
client.on('message', (topic, message) => {
const member = topic.split('/')[3]; // 从主题提取成员ID
const newState = message.toString();
if (familyMembers[member] !== newState) {
familyMembers[member] = newState;
updateHomeState();
}
});
// 更新整体家居状态
function updateHomeState() {
const allAway = Object.values(familyMembers).every(state => state === 'away');
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



