1. 项目背景
原始工程是 Nordic NRF5340 的 Matter 温度传感器示例程序,UpdateTemperatureMeasurement() 使用线性递增方式模拟温度数据上报到 Matter Temperature Measurement 集群,不读取真实传感器。
目标:接入真实 SHT30 温湿度传感器,同时上报温度和湿度到 Matter 网络。
2. 工程创建过程
本项目基于 Nordic nRF Connect SDK v3.2.4 的 Matter 温度传感器示例工程改造而来。
2.1 环境准备
1. 安装 VS Code + nRF Connect for Desktop 插件2. 安装 nRF Command Line Tools3. 安装 Python 3.x(已包含在 NCS 安装包中)4. 安装 west(pip install west)
2.2 导入示例工程
1. 打开 nRF Connect for Desktop,切换到 Applications 标签2. 在左侧边栏搜索或浏览找到 Matter Temperature Sensor 示例3. 点击 Create a new project,选择目标芯片(如 nRF54L15DK)4. 选择 SDK 版本(推荐 v3.2.4),点击 Create5. 等待初始化完成,VS Code 会自动打开新工程
如果没有 nRF Connect Desktop,也可在终端手动克隆:
2.3 工程目录结构(导入后初始状态)
2.4 本项目改造步骤
步骤 1: 在 boards/*.overlay 中添加 I2C 节点(&i2c21)和 SHT30 设备树配置步骤 2: 修改 prj.conf,启用 CONFIG_SENSOR、CONFIG_SHT3XD 等驱动步骤 3: 重写 app_task.cpp,将模拟温度改为 SHT30 真实读取步骤 4: 在 ZAP 中添加 RelativeHumidityMeasurement 集群,支持湿度上报步骤 5: 更新各 board overlay,适配不同芯片
3. 项目结构(改造后完整目录)
4. 硬件配置
目标板: nRF54L15DK(主要目标)
传感器接线:SHT30 - nRF54L15DKVCC - 3V3GND - GNDSCL - P1.11SDA - P1.12ADDR - GND(地址 0x44)
I2C 硬件说明:nRF54L15 的 device tree 中没有预置 I2C 节点,需要在 board overlay 中手动添加 &i2c21 和 &pinctrl 配置。
5. 配置文件修改
5.1 prj.conf — 启用传感器驱动
关键说明:- CONFIG_SHT3XD_SINGLE_SHOT_MODE 改为单次触发模式,默认是 PERIODIC(周期性),会持续占用 I2C 总线- CONFIG_SHT3XD_REPEATABILITY_HIGH 高精度模式,测量时间约 15ms
5.2 boards/nrf54l15dk_nrf54l15_cpuapp.overlay — I2C + SHT30 设备节点
关键说明: &i2c21 节点在 nRF54L15 基础 DTS 中不存在,必须在 overlay 中创建 设备节点标签为 sht3xd@44,对应 DT_INST(0, sensirion_sht3xd) 宏 pinctrl 定义了 I2C 引脚的默认状态和睡眠状态
6. 应用层代码修改
6.1 app_task.h — 新增传感器相关成员
6.2 app_task.cpp — 传感器线程架构
设计思路:传感器读取(阻塞约 15ms)放在独立线程中,避免阻塞 Matter 主线程的事件分发。
线程协作流程: 主线程(Main Thread):运行 Matter stack、commissioning、DispatchNextTask() 循环 传感器线程(sht30_reader):k_sem_take() 等待信号量,调用 sensor_sample_fetch() 读取传感器,通过 ScheduleWork() 回调通知主线程更新集群 定时器每 10 秒触发一次,通过 k_sem_give() 唤醒传感器线程
传感器初始化 InitSensor():
定时器回调 UpdateMeasurementTimeoutCallback():
启动流程:
7. Matter 数据模型修改
7.1 为什么要修改 ZAP 文件
需要在 Endpoint 1 上新增 Relative Humidity Measurement 集群,使 Matter 网络可以订阅湿度数据。
7.2 修改 temperature_sensor.zap
在 endpoint 1 的 clusters 数组末尾添加:
7.3 同步更新 zap-generated 文件
由于没有 ZAP CLI 工具,需要手动更新以下文件:
endpoint_config.h:- GENERATED_ATTRIBUTE_COUNT: 183 -> 188(+5 个湿度属性)- 添加湿度属性的 attribute 元数据(INT16U 类型,不是 HUMIDITY)- GENERATED_CLUSTER_COUNT: 18 -> 19(+1 个集群)- 添加 Relative Humidity 集群定义(clusterId = 0x00000405)- GENERATED_ENDPOINT_TYPES: endpoint 1 的 cluster 数量 3 -> 4,clusterSize 12 -> 52- ATTRIBUTE_MAX_SIZE: 164 -> 176
gen_config.h:- MATTER_DM_RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT: (0) -> (1)- 添加 ZCL_USING_RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER_SERVER- 添加 MATTER_DM_PLUGIN_RELATIVE_HUMIDITY_MEASUREMENT
callback-stub.cpp:- 添加 case app::Clusters::RelativeHumidityMeasurement::Id- 添加 emberAfRelativeHumidityMeasurementClusterInitCallback() 弱定义
PluginApplicationCallbacks.h:- 添加 MatterRelativeHumidityMeasurementPluginServerInitCallback() 函数声明- 添加到 MATTER_PLUGINS_INIT 宏
7.4 关键命名空间和类型
用途 -> 正确写法:- 集群命名空间: Clusters::RelativeHumidityMeasurement(不是 RelativeHumidity)- 集群 ID: 0x0405(十进制 1029)- 属性类型: INT16U(ZCL_HUMIDITY_ATTRIBUTE_TYPE 在 NCS v3.2.4 中不存在)
8. 踩坑记录
坑 1: 传感器通道名称错误现象: Failed to fetch SHT30 sample: -5(EIO)原因: 代码使用了 SENSOR_CHAN_DIE_TEMP,但驱动实际输出的是 SENSOR_CHAN_AMBIENT_TEMP解决: 改为 SENSOR_CHAN_AMBIENT_TEMP
坑 2: I2C 节点不存在于基础 DTS现象: parse error: undefined node label 'i2c21'原因: nRF54L15 的基础 device tree 中没有 I2C 节点解决: 在 overlay 中同时定义 &i2c21 和 &pinctrl 子节点
坑 3: Matter commissioning 被阻塞现象: 配网到 "Long dispatch time: 349 ms" 后卡住原因: sensor_sample_fetch() 在单次高精度模式下阻塞约 15ms,期间 Matter 主线程的事件分发被阻塞,导致 commissioning 无法完成解决: 将传感器读取放入独立线程 sht30_reader,通过信号量触发,主线程只负责调用 ScheduleWork() 更新集群属性
坑 4: humidity 类型不存在现象: 'ZCL_HUMIDITY_ATTRIBUTE_TYPE' was not declared原因: NCS v3.2.4 的 ZAP 工具不识别 humidity 类型别名解决: 在 endpoint_config.h 中使用 ZAP_TYPE(INT16U) 代替 ZAP_TYPE(HUMIDITY)
坑 5: 周期性模式首次读取失败现象: 逻辑分析仪看到 SHT30 回复 NAK原因: 驱动默认使用 PERIODIC 模式,初始化后立即读取时测量数据尚未准备好解决: 改用 CONFIG_SHT3XD_SINGLE_SHOT_MODE,每次读取前主动触发测量
9. 构建与烧录
# 完整构建(overlay 有修改时需要 --pristine)west build --board nrf54l15dk/nrf54l15/cpuapp --pristine
# 增量构建west build --board nrf54l15dk/nrf54l15/cpuapp
# 烧录west flash
# 调试日志west flash --runner jlink && JLinkRTTLogger &
10. 验证方法
原始工程是 Nordic NRF5340 的 Matter 温度传感器示例程序,UpdateTemperatureMeasurement() 使用线性递增方式模拟温度数据上报到 Matter Temperature Measurement 集群,不读取真实传感器。
目标:接入真实 SHT30 温湿度传感器,同时上报温度和湿度到 Matter 网络。
2. 工程创建过程
本项目基于 Nordic nRF Connect SDK v3.2.4 的 Matter 温度传感器示例工程改造而来。
2.1 环境准备
1. 安装 VS Code + nRF Connect for Desktop 插件2. 安装 nRF Command Line Tools3. 安装 Python 3.x(已包含在 NCS 安装包中)4. 安装 west(pip install west)
2.2 导入示例工程
1. 打开 nRF Connect for Desktop,切换到 Applications 标签2. 在左侧边栏搜索或浏览找到 Matter Temperature Sensor 示例3. 点击 Create a new project,选择目标芯片(如 nRF54L15DK)4. 选择 SDK 版本(推荐 v3.2.4),点击 Create5. 等待初始化完成,VS Code 会自动打开新工程
如果没有 nRF Connect Desktop,也可在终端手动克隆:
west init -m https://github.com/nrfconnect/sdk-nrf --mr v3.2.4 west update cd zephyr west app create ... # 参考 NCS 文档
2.3 工程目录结构(导入后初始状态)
temperature_sensor/ # 从 nRF Connect 导入的初始状态 ├── CMakeLists.txt ├── Kconfig ├── prj.conf # Debug 配置(默认启用 Matter 日志) ├── prj_release.conf # Release 配置 ├── boards/ │ └── nrf54l15dk_nrf54l15_cpuapp.overlay ├── src/ │ ├── main.cpp │ ├── app_task.cpp │ ├── app_task.h │ └── default_zap/ # Matter 集群配置(ZAP 格式) │ ├── temperature_sensor.zap │ └── zap-generated/ # ZAP 自动生成的代码 └── sysbuild/ # MCUboot 引导加载器配置 └── mcuboot/
2.4 本项目改造步骤
步骤 1: 在 boards/*.overlay 中添加 I2C 节点(&i2c21)和 SHT30 设备树配置步骤 2: 修改 prj.conf,启用 CONFIG_SENSOR、CONFIG_SHT3XD 等驱动步骤 3: 重写 app_task.cpp,将模拟温度改为 SHT30 真实读取步骤 4: 在 ZAP 中添加 RelativeHumidityMeasurement 集群,支持湿度上报步骤 5: 更新各 board overlay,适配不同芯片
3. 项目结构(改造后完整目录)
temperature_sensor/ ├── CMakeLists.txt # Zephyr 构建入口 ├── Kconfig # 项目 Kconfig 配置 ├── Kconfig.sysbuild # Sysbuild Kconfig ├── VERSION # 版本号 ├── prj.conf # 应用层 Kconfig fragment(调试) ├── prj_release.conf # 应用层 Kconfig fragment(发布) ├── sample.yaml # 测试用例配置 ├── sysbuild.conf # Sysbuild 全局配置 ├── sysbuild_internal.conf # Sysbuild 内部配置 │ ├── boards/ # 板级 device tree overlay │ ├── nrf52840dk_nrf52840.overlay │ ├── nrf5340dk_nrf5340_cpuapp.overlay │ ├── nrf54l15dk_nrf54l15_cpuapp.overlay # 主要目标板 │ ├── nrf54lm20dk_nrf54lm20a_cpuapp.overlay │ └── nrf54lm20dk_nrf54lm20a_cpuapp_internal.overlay │ ├── pm_static_*.yml # 电源管理静态配置(各 board) │ ├── sysbuild/ # Sysbuild 子系统 │ ├── mcuboot/ # MCUboot 引导加载器配置 │ │ ├── prj.conf │ │ ├── prj_release.conf │ │ ├── app.overlay │ │ └── boards/ # 各 board 的引导配置 │ └── ipc_radio/ # IPC 无线固件(nrf5340 网络核) │ ├── prj.conf │ └── prj_release.conf │ ├── src/ # 应用源码 │ ├── main.cpp # 应用入口,chip::AppTask │ ├── app_task.cpp # 传感器任务实现(SHT30 读取线程) │ ├── app_task.h │ ├── chip_project_config.h # Matter 项目配置 │ └── default_zap/ # ZAP 集群配置 │ ├── temperature_sensor.matter │ ├── temperature_sensor.zap │ └── zap-generated/ # ZAP 自动生成代码 │ ├── endpoint_config.h │ ├── gen_config.h │ ├── callback-stub.cpp │ ├── PluginApplicationCallbacks.h │ ├── CodeDrivenCallback.h │ ├── CodeDrivenInitShutdown.cpp │ ├── IMClusterCommandHandler.cpp │ └── access.h │ └── docs/ └── development_log.md # 本文档
4. 硬件配置
目标板: nRF54L15DK(主要目标)
传感器接线:SHT30 - nRF54L15DKVCC - 3V3GND - GNDSCL - P1.11SDA - P1.12ADDR - GND(地址 0x44)
I2C 硬件说明:nRF54L15 的 device tree 中没有预置 I2C 节点,需要在 board overlay 中手动添加 &i2c21 和 &pinctrl 配置。
5. 配置文件修改
5.1 prj.conf — 启用传感器驱动
# SHT30 Temperature & Humidity Sensor CONFIG_SENSOR=y CONFIG_SHT3XD=y # Use single-shot mode (simpler, no timing issues) CONFIG_SHT3XD_SINGLE_SHOT_MODE=y CONFIG_SHT3XD_REPEATABILITY_HIGH=y # I2C configuration for SHT30 CONFIG_I2C=y
关键说明:- CONFIG_SHT3XD_SINGLE_SHOT_MODE 改为单次触发模式,默认是 PERIODIC(周期性),会持续占用 I2C 总线- CONFIG_SHT3XD_REPEATABILITY_HIGH 高精度模式,测量时间约 15ms
5.2 boards/nrf54l15dk_nrf54l15_cpuapp.overlay — I2C + SHT30 设备节点
/* SHT30 temperature and humidity sensor on I2C21 (P1.11 SCL, P1.12 SDA) */
&i2c21 {
status = "okay";
pinctrl-0 = <&i2c21_default>;
pinctrl-1 = <&i2c21_sleep>;
pinctrl-names = "default", "sleep";
sht3xd@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
status = "okay";
};
};
&pinctrl {
i2c21_default: i2c21_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 1, 12)>,
<NRF_PSEL(TWIM_SCL, 1, 11)>;
bias-pull-up;
};
};
i2c21_sleep: i2c21_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 1, 12)>,
<NRF_PSEL(TWIM_SCL, 1, 11)>;
low-power-enable;
bias-pull-up;
};
};
};关键说明: &i2c21 节点在 nRF54L15 基础 DTS 中不存在,必须在 overlay 中创建 设备节点标签为 sht3xd@44,对应 DT_INST(0, sensirion_sht3xd) 宏 pinctrl 定义了 I2C 引脚的默认状态和睡眠状态
6. 应用层代码修改
6.1 app_task.h — 新增传感器相关成员
private: CHIP_ERROR Init(); CHIP_ERROR InitSensor(); k_timer mTimer; const struct device *mSensor = nullptr; struct k_sem mSensorSem; // 信号量,触发传感器读取 static void SensorThreadMain(void *arg1, void *arg2, void *arg3); static void UpdateMeasurementTimeoutCallback(k_timer *timer); static void ButtonEventHandler(Nrf::ButtonState state, Nrf::ButtonMask hasChanged); k_thread mSensorThread; K_KERNEL_STACK_MEMBER(mSensorStack, 1024); // 1KB 栈空间 int16_t mTemperatureSensorMaxValue = 0; int16_t mTemperatureSensorMinValue = 0; int16_t mCurrentTemperature = 0; int16_t mCurrentHumidity = 0; };
6.2 app_task.cpp — 传感器线程架构
设计思路:传感器读取(阻塞约 15ms)放在独立线程中,避免阻塞 Matter 主线程的事件分发。
线程协作流程: 主线程(Main Thread):运行 Matter stack、commissioning、DispatchNextTask() 循环 传感器线程(sht30_reader):k_sem_take() 等待信号量,调用 sensor_sample_fetch() 读取传感器,通过 ScheduleWork() 回调通知主线程更新集群 定时器每 10 秒触发一次,通过 k_sem_give() 唤醒传感器线程
传感器初始化 InitSensor():
CHIP_ERROR AppTask::InitSensor()
{
#if DT_NODE_HAS_STATUS(DT_INST(0, sensirion_sht3xd), okay)
mSensor = DEVICE_DT_GET(DT_INST(0, sensirion_sht3xd));
if (!mSensor || !device_is_ready(mSensor)) {
return CHIP_ERROR_UNINITIALIZED;
}
LOG_INF("SHT30 sensor initialized successfully");
#else
mSensor = nullptr;
LOG_WRN("SHT30 sensor not found in device tree");
#endif
return CHIP_NO_ERROR;
}传感器线程 SensorThreadMain():void AppTask::SensorThreadMain(void *arg1, void *arg2, void *arg3)
{
AppTask &app = AppTask::Instance();
while (true) {
k_sem_take(&app.mSensorSem, K_FOREVER); // 等待定时器信号
if (app.mSensor != nullptr) {
struct sensor_value temp_val, humid_val;
int ret = sensor_sample_fetch(app.mSensor); // 发送测量命令 + 等待
if (ret == 0) {
ret = sensor_channel_get(app.mSensor, // 读取温度
SENSOR_CHAN_AMBIENT_TEMP, &temp_val); // 注意:不是 DIE_TEMP
}
if (ret == 0) {
ret = sensor_channel_get(app.mSensor, // 读取湿度
SENSOR_CHAN_HUMIDITY, &humid_val);
}
if (ret == 0) {
app.mCurrentTemperature = sensor_value_to_double(&temp_val) * 100;
app.mCurrentHumidity = sensor_value_to_double(&humid_val) * 100;
// 在 Matter 主线程中更新集群
DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t) {
// 更新 Temperature Measurement 集群
Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Set(
kTemperatureSensorEndpointId, AppTask::Instance().mCurrentTemperature);
// 更新 Relative Humidity 集群
Clusters::RelativeHumidityMeasurement::Attributes::MeasuredValue::Set(
kTemperatureSensorEndpointId, AppTask::Instance().mCurrentHumidity);
}, 0);
}
}
}
}定时器回调 UpdateMeasurementTimeoutCallback():
void AppTask::UpdateMeasurementTimeoutCallback(k_timer *timer)
{
if (!timer || !timer->user_data) return;
AppTask *app = reinterpret_cast<AppTask *>(timer->user_data);
k_sem_give(&app->mSensorSem); // 发出信号量,唤醒传感器线程
}启动流程:
CHIP_ERROR AppTask::StartApp()
{
ReturnErrorOnFailure(Init());
k_sem_init(&mSensorSem, 0, 1);
// 创建传感器读取线程(用户线程)
k_thread_create(&mSensorThread, mSensorStack,
K_KERNEL_STACK_SIZEOF(mSensorStack),
SensorThreadMain, this, nullptr, nullptr,
-1, K_USER, K_NO_WAIT);
k_thread_name_set(&mSensorThread, "sht30_reader");
// 启动定时器,每 10 秒触发一次测量
k_timer_init(&mTimer, UpdateMeasurementTimeoutCallback, nullptr);
k_timer_user_data_set(&mTimer, this);
k_timer_start(&mTimer,
K_MSEC(kMeasurementIntervalMs),
K_MSEC(kMeasurementIntervalMs));
while (true) {
Nrf::DispatchNextTask(); // Matter 事件循环
}
}7. Matter 数据模型修改
7.1 为什么要修改 ZAP 文件
需要在 Endpoint 1 上新增 Relative Humidity Measurement 集群,使 Matter 网络可以订阅湿度数据。
7.2 修改 temperature_sensor.zap
在 endpoint 1 的 clusters 数组末尾添加:
{
"name": "Relative Humidity Measurement",
"code": 1029,
"mfgCode": null,
"define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER",
"side": "server",
"enabled": 1,
"attributes": [
{ "name": "MeasuredValue", "code": 0, "type": "humidity", "included": 1 },
{ "name": "MinMeasuredValue", "code": 1, "type": "humidity", "defaultValue": "0" },
{ "name": "MaxMeasuredValue", "code": 2, "type": "humidity", "defaultValue": "10000" },
{ "name": "FeatureMap", "code": 65532, "type": "bitmap32" },
{ "name": "ClusterRevision", "code": 65533, "type": "int16u", "defaultValue": "3" }
// + GeneratedCommandList, AcceptedCommandList, AttributeList
]
}7.3 同步更新 zap-generated 文件
由于没有 ZAP CLI 工具,需要手动更新以下文件:
endpoint_config.h:- GENERATED_ATTRIBUTE_COUNT: 183 -> 188(+5 个湿度属性)- 添加湿度属性的 attribute 元数据(INT16U 类型,不是 HUMIDITY)- GENERATED_CLUSTER_COUNT: 18 -> 19(+1 个集群)- 添加 Relative Humidity 集群定义(clusterId = 0x00000405)- GENERATED_ENDPOINT_TYPES: endpoint 1 的 cluster 数量 3 -> 4,clusterSize 12 -> 52- ATTRIBUTE_MAX_SIZE: 164 -> 176
gen_config.h:- MATTER_DM_RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT: (0) -> (1)- 添加 ZCL_USING_RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER_SERVER- 添加 MATTER_DM_PLUGIN_RELATIVE_HUMIDITY_MEASUREMENT
callback-stub.cpp:- 添加 case app::Clusters::RelativeHumidityMeasurement::Id- 添加 emberAfRelativeHumidityMeasurementClusterInitCallback() 弱定义
PluginApplicationCallbacks.h:- 添加 MatterRelativeHumidityMeasurementPluginServerInitCallback() 函数声明- 添加到 MATTER_PLUGINS_INIT 宏
7.4 关键命名空间和类型
用途 -> 正确写法:- 集群命名空间: Clusters::RelativeHumidityMeasurement(不是 RelativeHumidity)- 集群 ID: 0x0405(十进制 1029)- 属性类型: INT16U(ZCL_HUMIDITY_ATTRIBUTE_TYPE 在 NCS v3.2.4 中不存在)
8. 踩坑记录
坑 1: 传感器通道名称错误现象: Failed to fetch SHT30 sample: -5(EIO)原因: 代码使用了 SENSOR_CHAN_DIE_TEMP,但驱动实际输出的是 SENSOR_CHAN_AMBIENT_TEMP解决: 改为 SENSOR_CHAN_AMBIENT_TEMP
坑 2: I2C 节点不存在于基础 DTS现象: parse error: undefined node label 'i2c21'原因: nRF54L15 的基础 device tree 中没有 I2C 节点解决: 在 overlay 中同时定义 &i2c21 和 &pinctrl 子节点
坑 3: Matter commissioning 被阻塞现象: 配网到 "Long dispatch time: 349 ms" 后卡住原因: sensor_sample_fetch() 在单次高精度模式下阻塞约 15ms,期间 Matter 主线程的事件分发被阻塞,导致 commissioning 无法完成解决: 将传感器读取放入独立线程 sht30_reader,通过信号量触发,主线程只负责调用 ScheduleWork() 更新集群属性
坑 4: humidity 类型不存在现象: 'ZCL_HUMIDITY_ATTRIBUTE_TYPE' was not declared原因: NCS v3.2.4 的 ZAP 工具不识别 humidity 类型别名解决: 在 endpoint_config.h 中使用 ZAP_TYPE(INT16U) 代替 ZAP_TYPE(HUMIDITY)
坑 5: 周期性模式首次读取失败现象: 逻辑分析仪看到 SHT30 回复 NAK原因: 驱动默认使用 PERIODIC 模式,初始化后立即读取时测量数据尚未准备好解决: 改用 CONFIG_SHT3XD_SINGLE_SHOT_MODE,每次读取前主动触发测量
9. 构建与烧录
# 完整构建(overlay 有修改时需要 --pristine)west build --board nrf54l15dk/nrf54l15/cpuapp --pristine
# 增量构建west build --board nrf54l15dk/nrf54l15/cpuapp
# 烧录west flash
# 调试日志west flash --runner jlink && JLinkRTTLogger &
10. 验证方法
10.1 硬件环境
homepod
iphone手机。
10.2 在iphone家庭中添加设备
打开串口接到开发板上,上电找到二维码信息:

把这段代码复制到浏览器中打开:


添加好后就可以成功的看到传感器的信息了:

这们我们就可以把NRF54L15成功的接入了苹果生态,我们可以实时知道家里的环境,也可以能过sir随时询问家里的情况。
附作品视频介绍:
我要赚赏金
