news 2026/9/14 17:24:12

ESP32 Arduino Matter 占用传感器端点(MatterOccupancySensor)开发实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP32 Arduino Matter 占用传感器端点(MatterOccupancySensor)开发实战指南

ESP32 Arduino Matter 占用传感器端点(MatterOccupancySensor)开发实战指南

【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32

本文以 Arduino-ESP32 核心库中的MatterOccupancySensor类为对象,系统讲解如何在 ESP32 系列芯片上基于 Matter 协议实现标准占用传感器(Occupancy Sensor)端点,涵盖 API 用法、HoldTime 保持时间配置、传感器类型选择、真实 PIR 传感器接入以及 HomeKit / Alexa / Google Home 的联调方法。读完本文,你将能独立编写并配网一个符合 Matter 标准的占用检测设备,并掌握其底层实现原理。

一、MatterOccupancySensor 概述

MatterOccupancySensor是 Arduino-ESP32 Matter 库提供的一个占用传感器端点类(见 MatterOccupancySensor.h),其作用是在 Matter 网络中提供一个符合 Matter 占用感知标准的端点,用于检测并上报"有人占用(occupied)"与"无人占用(unoccupied)"两种状态,典型应用包括 PIR 人体红外传感器、门磁接触式检测等。

该类的核心特性:

  • 占用状态上报:支持 occupied / unoccupied 双状态实时上报;
  • 多种传感器类型:PIR(被动红外)、超声波(Ultrasonic)、PIR+超声波组合、物理接触(Physical Contact);
  • HoldTime 属性:配置传感器在检测到占用后保持"occupied"状态的时长;
  • HoldTimeLimits:提供最小值、最大值、默认值三段式校验与控制器参考元数据;
  • HoldTime 变更回调:Matter 控制器修改 HoldTime 时实时通知应用;
  • 简单布尔状态:支持bool运算符直接读写;
  • 只读传感器:无任何控制功能,仅上报状态;
  • 状态自动更新:应用侧改状态后自动同步到 Matter 属性;
  • 生态集成:可接入 Apple HomeKit、Amazon Alexa、Google Home;
  • Matter 标准合规:实现基于 Matter Occupancy Sensing Cluster。

典型应用场景包括:人体移动检测(PIR)、占用检测、安防系统、智能照明自动化(有人开灯、无人关灯)、能耗管理(无人时自动关闭灯光/空调)。

从源码结构看,MatterOccupancySensor继承自MatterEndPoint基类,并在内部封装了 esp-matter 的occupancy_sensor::create()端点创建逻辑与 Occupancy Sensing Cluster 的属性和特性(feature flags)配置。

二、API 参考

2.1 构造函数

MatterOccupancySensor();

创建一个新的 Matter 占用传感器端点对象。该构造函数本身不创建 Matter 端点,真正的端点创建发生在begin()中。对象通常在全局作用域声明,例如:

MatterOccupancySensor OccupancySensor;

2.2 初始化

begin
bool begin(bool _occupancyState = false, OccupancySensorType_t _occupancySensorType = OCCUPANCY_SENSOR_TYPE_PIR);

初始化占用传感器端点,参数说明:

  • _occupancyState:初始占用状态(true= 有人占用,false= 无人占用,默认false);
  • _occupancySensorType:传感器类型(默认OCCUPANCY_SENSOR_TYPE_PIR)。

返回true表示初始化成功,false表示失败。

从 MatterOccupancySensor.cpp 的实现可以看到,begin()内部会:

  1. 调用ArduinoMatter::_init()完成 Matter 运行时初始化;
  2. 通过occupancy_sensor::create()创建端点,并把当前对象指针作为私有数据传入;
  3. 根据传感器类型设置对应的 feature flags(passive_infraredultrasonicphysical_contactother);
  4. 注册自定义的OccupancySensingAttrAccessWrapper属性访问接口,用于支持 HoldTime / HoldTimeLimits 属性(这两个属性属于 Matter 1.4+ 新增,由 CHIP server 内部管理,不会随occupancy_sensor::create()自动添加);
  5. 通过create_hold_time()/create_hold_time_limits()为 Occupancy Sensing 集群补充创建这两个属性。
end
void end();

停止处理 Matter 占用传感器事件。实现中将started标志置为false,此后setOccupancy()setHoldTime()等操作会因未启动而返回false。析构函数会自动调用end()

2.3 传感器类型枚举

OccupancySensorType_t定义于 MatterOccupancySensor.h:

枚举值含义对应 feature flag
OCCUPANCY_SENSOR_TYPE_PIR被动红外(PIR)传感器passive_infrared
OCCUPANCY_SENSOR_TYPE_ULTRASONIC超声波传感器ultrasonic
OCCUPANCY_SENSOR_TYPE_PIR_AND_ULTRASONICPIR 与超声波组合passive_infrared \| ultrasonic
OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT物理接触传感器physical_contact

这些枚举值直接映射到 Matter 的OccupancySensorTypeEnum标准枚举。组合类型在内部还会通过occupancySensorTypeBitmap映射表设置occupancy_sensor_type_bitmap属性(PIR=0x01、Ultrasonic=0x02、PhysicalContact=0x04 的位图组合)。

2.4 占用状态控制

bool setOccupancy(bool _occupancyState); bool getOccupancy();
  • setOccupancy():设置占用状态(true= occupied,false= unoccupied),成功返回true。从实现看,若状态无变化会直接返回true跳过处理;有变化时通过updateAttributeVal()更新 Occupancy 属性并同步内部成员,这样 Matter 控制器才能收到状态变更通知;
  • getOccupancy():返回当前占用状态,true表示有人,false表示无人。

2.5 HoldTime 控制

bool setHoldTime(uint16_t _holdTime_seconds); uint16_t getHoldTime();
  • setHoldTime():设置 HoldTime 值(单位:秒)。HoldTime 决定传感器在最后一次检测后维持"occupied"状态的时长。重要:该函数必须在Matter.begin()之后调用,因为它依赖 Matter 事件循环(实现中通过chip::DeviceLayer::SystemLayer().ScheduleLambda()将属性更新调度到 Matter 事件循环上下文执行,以避免栈锁错误)。若holdTimeMax_seconds大于 0(即已设置限制),新值必须落在 min/max 范围内,否则返回false
  • getHoldTime():返回当前 HoldTime 值(秒)。
bool setHoldTimeLimits(uint16_t _holdTimeMin_seconds, uint16_t _holdTimeMax_seconds, uint16_t _holdTimeDefault_seconds);

设置 HoldTime 限制(最小值、最大值、默认值),为控制器提供有效范围校验与参考指导。参数说明:

  • _holdTimeMin_seconds:HoldTime 最小值(秒);
  • _holdTimeMax_seconds:HoldTime 最大值(秒);
  • _holdTimeDefault_seconds:HoldTime 默认/推荐值(秒),作为控制器的参考元数据。

注意事项

  • 必须在Matter.begin()之后调用(依赖 Matter 事件循环);
  • holdTimeDefault_seconds仅是提供给 Matter 控制器的信息性元数据(推荐默认值),不会自动设置 HoldTime 属性本身——要真正设置值必须调用setHoldTime()
  • 若当前 HoldTime 值超出新设置的范围,会自动被调整到最近的边界(最小值或最大值)。这一逻辑在源码中体现为:先比较holdTime_seconds与新的 min/max,超出时构造adjustedHoldTime并通过SetHoldTimeLimitsAndHoldTimeInEventLoop()一次性在事件循环中同时更新限制与 HoldTime;
  • 实现中还会做参数自检:min > maxdefault不在[min, max]区间内都会返回false

2.6 onHoldTimeChange 回调

using HoldTimeChangeCB = std::function<bool(uint16_t holdTime_seconds)>; void onHoldTimeChange(HoldTimeChangeCB onHoldTimeChangeCB);

注册一个回调函数,当 Matter 控制器修改 HoldTime 值时被调用。回调接收新的 HoldTime 值,返回true表示接受变更,返回false表示拒绝。

示例:

OccupancySensor.onHoldTimeChange([](uint16_t holdTime_seconds) -> bool { Serial.printf("HoldTime changed to %u seconds\n", holdTime_seconds); return true; // 接受变更 });

从 MatterOccupancySensor.cpp 实现看,HoldTime 的写入拦截是通过自定义OccupancySensingAttrAccessWrapper(继承chip::app::AttributeAccessInterface)完成的:它先按 HoldTimeLimits 做标准校验,再调用用户回调,回调返回false时返回ConstraintError拒绝写入,通过后才调用OccupancySensing::SetHoldTime()并同步内部成员变量。这样既保留了官方 server 的校验逻辑,又扩展了用户回调能力。

2.7 运算符重载

operator bool(); void operator=(bool _occupancyState);
  • operator bool():直接返回当前占用状态,可用于条件判断:
if (mySensor) { Serial.println("Room is occupied"); } else { Serial.println("Room is unoccupied"); }
  • operator=:设置占用状态,等价于setOccupancy()
mySensor = true; // 设为 occupied mySensor = false; // 设为 unoccupied

三、基础示例:MatterOccupancySensor

完整示例见 MatterOccupancySensor.ino,演示了如何创建一个 Matter 占用传感器设备,并模拟每 2 分钟切换一次占用状态。

3.1 端点声明与全局配置

#include <Arduino.h> #include <Matter.h> #if !CONFIG_ENABLE_CHIPOBLE // 若设备可通过 BLE 配网,则无需 WiFi,可节省 flash 空间 #include <WiFi.h> #endif // Matter 占用传感器端点 MatterOccupancySensor OccupancySensor; #if !CONFIG_ENABLE_CHIPOBLE const char *ssid = "your-ssid"; // 修改为你的 WiFi SSID const char *password = "your-password"; // 修改为你的 WiFi 密码 #endif // 使用板载 BOOT 按键做解除配网(decommission) const uint8_t buttonPin = BOOT_PIN; const uint32_t decommissioningTimeout = 5000; // 长按 5 秒解除配网

CONFIG_ENABLE_CHIPOBLE启用时设备通过 BLE 配网(CHIPoBLE),不需要手工连接 WiFi;未启用时(如 ESP32、ESP32-S2 芯片不支持 BLE 配网)则必须显式提供 WiFi 凭据。

3.2 setup() 初始化流程

void setup() { pinMode(buttonPin, INPUT_PULLUP); Serial.begin(115200); #if !CONFIG_ENABLE_CHIPOBLE WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); #endif // 设置初始占用状态为 false,传感器类型为 PIR(默认) OccupancySensor.begin(); // Matter 初始化必须是最后一步:在所有 EndPoint 初始化完成后调用 Matter.begin(); if (!Matter.isDeviceCommissioned()) { Serial.println("Matter Node is not commissioned yet."); Serial.println("Initiate the device discovery in your Matter environment."); Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); // 等待 Matter 占用传感器完成配网 uint32_t timeCount = 0; while (!Matter.isDeviceCommissioned()) { delay(100); if ((timeCount++ % 50) == 0) { // 50*100ms = 5 秒 Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); } } Serial.println("Matter Node is commissioned and connected to the network. Ready for use."); } }

关键要点:

  1. OccupancySensor.begin()必须在Matter.begin()之前完成端点注册;
  2. Matter.begin()是最后一步,用于启动整个 Matter 协议栈;
  3. 配网信息(手动配对码 + 二维码 URL)在配网前通过串口打印,配网期间阻塞等待;
  4. Matter.isDeviceCommissioned()用于判断设备是否已被 Matter 网络(如 HomePod、Nest Hub、Echo)接受。

3.3 模拟传感器与主循环

bool simulatedHWOccupancySensor() { // 模拟占用传感器:每 2 分钟切换一次状态 static bool occupancyState = false; static uint32_t lastTime = millis(); const uint32_t occupancyTimeout = 120000; // 2 分钟 if (millis() - lastTime > occupancyTimeout) { occupancyState = !occupancyState; lastTime = millis(); } return occupancyState; } void loop() { // 按钮消抖与解除配网逻辑(长按 5 秒) if (digitalRead(buttonPin) == LOW && !button_state) { button_time_stamp = millis(); button_state = true; } if (button_state && digitalRead(buttonPin) == HIGH) { button_state = false; } uint32_t time_diff = millis() - button_time_stamp; if (button_state && time_diff > decommissioningTimeout) { Serial.println("Decommissioning Occupancy Sensor Matter Accessory. It shall be commissioned again."); Matter.decommission(); button_time_stamp = millis(); } // 读取模拟传感器并同步到 Matter 属性 OccupancySensor.setOccupancy(simulatedHWOccupancySensor()); delay(50); }

loop()中通过setOccupancy()将传感器读数持续同步到 Matter 属性,Matter 协议栈会自动向控制器推送状态变更。按钮逻辑实现"长按 5 秒解除配网"的出厂重置功能。

3.4 编译与烧录要点

  • 在 Arduino IDE 中打开 MatterOccupancySensor.ino;
  • 选择目标 ESP32 开发板(Tools > Board);
  • 分区方案选择"Huge APP (3MB No OTA/1MB SPIFFS)"
  • 开启"Erase All Flash Before Sketch Upload"
  • 串口监视器波特率115200

串口预期输出示例(配网信息):

Manual pairing code: 34970112332 QR code URL: MT:6FCJ142C00KA0648G00... Matter Node not commissioned yet. Waiting for commissioning. ... Matter Node is commissioned and connected to the network. Ready for use.

配网完成后,占用传感器每 2 分钟自动切换 occupied/unoccupied,Matter 控制器(手机 App / 智能家居中枢)可实时收到状态更新。

四、HoldTime 进阶示例:MatterOccupancyWithHoldTime

完整示例见 MatterOccupancyWithHoldTime.ino,它在前一个示例基础上增加了 HoldTime 完整功能演示,重点覆盖:

  • Matter.begin()之后配置 HoldTimeLimits;
  • 设置并持久化 HoldTime 值(通过 Preferences/NVS 跨重启保持);
  • 使用onHoldTimeChange()回调接收控制器的实时修改;
  • 在传感器模拟逻辑中实现 HoldTime 过期自动切换为空闲。

4.1 HoldTime 常量与 Preferences 持久化

const uint16_t HOLD_TIME_MIN = 0; // 最小 HoldTime(秒) const uint16_t HOLD_TIME_MAX = 3600; // 最大 HoldTime(秒,1 小时) const uint16_t HOLD_TIME_DEFAULT = 30; // 默认 HoldTime(秒) MatterOccupancySensor OccupancySensor; Preferences matterPref; const char *holdTimePrefKey = "HoldTime";

setup() 中先恢复上次保存的 HoldTime:

matterPref.begin("MatterPrefs", false); uint16_t storedHoldTime = matterPref.getUShort(holdTimePrefKey, HOLD_TIME_DEFAULT); // 校验存储值是否在合法范围内 if (storedHoldTime < HOLD_TIME_MIN || storedHoldTime > HOLD_TIME_MAX) { uint16_t invalidValue = storedHoldTime; storedHoldTime = HOLD_TIME_DEFAULT; Serial.printf("Invalid stored HoldTime (%u), using default: %u seconds\n", invalidValue, HOLD_TIME_DEFAULT); } else if (storedHoldTime != HOLD_TIME_DEFAULT) { Serial.printf("Restored HoldTime from Preferences: %u seconds\n", storedHoldTime); }

4.2 注册 HoldTime 变更回调并持久化

OccupancySensor.onHoldTimeChange([](uint16_t holdTime_seconds) -> bool { Serial.printf("HoldTime changed to %u seconds by Matter Controller\n", holdTime_seconds); // 将新 HoldTime 写入 Preferences,实现跨重启持久化 matterPref.putUShort(holdTimePrefKey, holdTime_seconds); // 回调返回 false 可拒绝变更,这里始终接受并同步模拟器 return true; });

4.3 初始化顺序:先 begin,后设 Limits 与 HoldTime

// 设置初始占用状态为 false,传感器类型为 PIR(默认) OccupancySensor.begin(); // Matter 初始化必须是最后一步 Matter.begin(); // 在 Matter.begin() 之后设置 HoldTimeLimits(可选,但推荐用于校验) if (!OccupancySensor.setHoldTimeLimits(HOLD_TIME_MIN, HOLD_TIME_MAX, HOLD_TIME_DEFAULT)) { Serial.println("Warning: Failed to set HoldTimeLimits"); } else { Serial.printf("HoldTimeLimits set: Min=%u, Max=%u, Default=%u seconds\n", HOLD_TIME_MIN, HOLD_TIME_MAX, HOLD_TIME_DEFAULT); } // 设置初始 HoldTime(优先使用存储值,否则用默认值) if (!OccupancySensor.setHoldTime(storedHoldTime)) { Serial.printf("Warning: Failed to set HoldTime to %u seconds\n", storedHoldTime); } else { Serial.printf("HoldTime set to: %u seconds\n", storedHoldTime); } Serial.printf("Initial HoldTime: %u seconds\n", OccupancySensor.getHoldTime());

顺序非常关键setHoldTimeLimits()setHoldTime()都依赖Matter.begin()启动的 Matter 事件循环(SystemLayer),必须在Matter.begin()之后调用,否则会因SystemLayer未初始化而失败。

4.4 带 HoldTime 过期的传感器模拟

bool simulatedHWOccupancySensor() { static bool occupancyState = false; static uint32_t lastDetectionTime = 0; static uint32_t lastDetectionEvent = millis(); const uint32_t detectionInterval = 120000; // 每 2 分钟模拟一次检测 // 获取当前 HoldTime(可能已被 Matter 控制器修改),转换为毫秒 uint32_t holdTime_ms = OccupancySensor.getHoldTime() * 1000; // 先检查 HoldTime 是否过期(确保即使同一轮迭代有新检测也能正确过期) if (occupancyState && (millis() - lastDetectionTime > holdTime_ms)) { occupancyState = false; lastDetectionEvent = millis(); Serial.println("HoldTime expired. Switching to unoccupied state."); } // 再模拟周期性检测(放在过期检查之后,使新检测能立即重新触发占用) if (millis() - lastDetectionEvent > detectionInterval) { lastDetectionEvent = millis(); if (!occupancyState) { // 从无人切换到有人:启动保持计时 occupancyState = true; lastDetectionTime = millis(); Serial.printf("Occupancy detected! Holding state for %u seconds (HoldTime)\n", OccupancySensor.getHoldTime()); } else { // 已处于有人状态:新检测重置保持计时(模拟持续有人) lastDetectionTime = millis(); Serial.printf("Occupancy still detected. Resetting hold timer to %u seconds (HoldTime)\n", OccupancySensor.getHoldTime()); } } return occupancyState; }

模拟器对 HoldTime 与检测间隔关系的处理逻辑:

  • holdTime < detectionInterval:状态在 HoldTime 后切回无人,等待下一次检测;
  • holdTime == detectionInterval:检测持续到来时计时器不断重置,表现为持续占用;
  • holdTime > detectionInterval:检测持续到来时计时器重置(持续占用);检测停止后,从最后一次检测起 HoldTime 到期切换为空闲。

主循环与基础示例一致:OccupancySensor.setOccupancy(simulatedHWOccupancySensor());持续同步状态。

五、接入真实 PIR 传感器

两个示例的 README(MatterOccupancySensor/README.md、MatterOccupancyWithHoldTime/README.md)都给出了接入真实 PIR 传感器的完整方案。

5.1 硬件接线

以 HC-SR501、AM312 等常见 PIR 模块为例(典型三引脚:VCC、GND、OUT):

  • PIR VCC→ ESP32 3.3V 或 5V(以传感器规格为准);
  • PIR GND→ ESP32 GND;
  • PIR OUT→ ESP32 任意 GPIO(如 GPIO 4)。

5.2 代码改造

定义引脚并初始化:

const uint8_t pirPin = 4; // 修改为你的 PIR 引脚 // setup() 中: pinMode(pirPin, INPUT);

将模拟函数替换为真实读数(含 100ms 消抖,避免误触发):

bool simulatedHWOccupancySensor() { // 带消抖的 PIR 读数:HIGH = 检测到移动(有人),LOW = 无移动(无人) static bool lastState = false; static uint32_t lastChangeTime = 0; const uint32_t debounceTime = 100; // 100ms 消抖 bool currentState = digitalRead(pirPin) == HIGH; if (currentState != lastState) { if (millis() - lastChangeTime > debounceTime) { lastState = currentState; lastChangeTime = millis(); Serial.printf("Occupancy state changed: %s\r\n", currentState ? "OCCUPIED" : "UNOCCUPIED"); } } return lastState; }

配合 HoldTime 示例使用时,真实 PIR 的"最后一次检测后保持 HoldTime 时长再切回无人"的行为逻辑完全一致——simulatedHWOccupancySensor()仅提供状态输入,HoldTime 保持/过期逻辑无需改动。

PIR 使用小贴士(来自示例 README 的排障建议):

  • 部分 PIR 模块需要 5V 供电;
  • 上电后预留 30–60 秒让传感器稳定;
  • 可通过灵敏度与延时电位器调节检测范围;
  • 对误触发问题优先在软件中加入消抖。

六、智能家居生态集成与配网

设备烧录并启动后,使用 Matter 兼容中枢(如 Apple HomePod、Google Nest Hub、Amazon Echo)即可配网。

Apple Home:打开 Home App → "+" → Add Accessory → 扫描串口输出的二维码,或选择 "I Don't Have a Code or Cannot Scan" 手动输入配对码。配网完成后设备以占用传感器(Occupancy Sensor)形态出现在 Home App 中,可基于占用状态创建自动化(如有人时开灯)。

Amazon Alexa:Alexa App → More → Add Device → Matter → 扫码或手动输码完成设置,随后可查看占用读数并创建 Routine。

Google Home:Google Home App → "+" → Set up device → New device → Matter device → 扫码或输码,之后可查看占用读数并创建自动化。

配网失败时可长按 BOOT 键 5 秒解除配网(Matter.decommission()),或在 Arduino IDE 中开启 "Erase All Flash Before Sketch Upload" 擦除整片 flash 后重试。

支持的目标芯片

SoCWi-FiThreadBLE 配网状态
ESP32完整支持
ESP32-S2完整支持
ESP32-S3完整支持
ESP32-C3完整支持
ESP32-C5支持(仅 Thread)
ESP32-C6完整支持
ESP32-H2支持(仅 Thread)

配网注意事项

  • ESP32 与 ESP32-S2 不支持 BLE 配网,必须在代码中显式提供 WiFi 凭据;
  • ESP32-C6 虽支持 Thread,但 Arduino Matter 库预编译版本仅启用 Wi-Fi;若要 Thread 专用模式,需将 Arduino 作为 ESP-IDF 组件构建并禁用 Matter Wi-Fi station 特性;
  • ESP32-C5 预编译版本仅启用 Thread;若要 Wi-Fi 模式,需以 ESP-IDF 组件方式构建并仅保留 Wi-Fi station 网络。

七、底层实现原理:HoldTime 是如何工作的

从 MatterOccupancySensor.cpp 可以看出 HoldTime 机制的实现细节:

  1. 属性动态创建:HoldTime 与 HoldTimeLimits 是 Matter 1.4+ 引入、由 CHIP server 内部管理(MANAGED_INTERNALLY)的属性,occupancy_sensor::create()不会自动创建它们。begin()中通过 esp-matter 的create_hold_time()/create_hold_time_limits()在 Occupancy Sensing 集群上补充创建,且 HoldTimeLimits 仅在 HoldTime 创建成功后才创建。

  2. 自定义属性访问接口:类内定义了OccupancySensingAttrAccessWrapper,继承chip::app::AttributeAccessInterface并注册到AttributeAccessInterfaceRegistry。读取操作委托给标准OccupancySensing::Instance;写入操作则先解码新值,对照GetHoldTimeLimitsForEndpoint()获取的 HoldTimeLimits 做 ConstraintError 校验,再调用用户回调(回调返回false同样返回ConstraintError),最后调用OccupancySensing::SetHoldTime()并同步内部成员。

  3. 事件循环调度setHoldTime()/setHoldTimeLimits()内部通过SystemLayer().ScheduleLambda()把属性更新调度到 Matter 事件循环线程执行,这是因为MatterReportingAttributeChangeCallback()必须在 Matter 事件循环上下文中调用,否则会出现栈锁错误——这也是文档强调"必须在Matter.begin()之后调用"的根本原因。

  4. 内部状态一致性setHoldTimeLimits()在调度成功后才会提交成员变量(holdTimeMin/Max/Default_seconds),失败时保持不变;若当前 HoldTime 超出新范围,会计算adjustedHoldTime并一次性调度"设限制 + 调 HoldTime",确保属性与内部状态始终一致。

八、常见问题排查

  • 设备配网时不可见:确认 Wi-Fi 或 Thread 连接配置正确(参考上文芯片支持表与注意事项);
  • 占用读数不更新:确认模拟函数被正确调用;真实传感器场景检查接线与库初始化;
  • 状态不变化:模拟传感器每 2 分钟(120000ms)切换一次,耐心等待或缩短occupancyTimeout便于测试;
  • HoldTime 不生效:确认setHoldTimeLimits()setHoldTime()均在Matter.begin()之后调用,并在串口检查报错信息;
  • HoldTime 重启后丢失:确认 Preferences 已初始化且回调正确执行putUShort(),观察串口 "HoldTime changed" 日志;
  • PIR 检测不到移动:检查 VCC/GND/OUT 接线、供电电压(3.3V/5V)、预留 30–60 秒稳定时间、调节灵敏度电位器、确保检测区域无遮挡,并可先直接在串口打印 GPIO 值验证;
  • 配网失败:长按按键解除配网后重试,或开启 "Erase All Flash Before Sketch Upload" 擦除 flash;
  • 无串口输出:确认波特率 115200 与 USB 连接。

九、进一步阅读

  • Matter 总览文档:matter.rst
  • Matter 端点基类说明:matter_ep.rst
  • 其他传感器端点文档:温湿度(ep_temperature_sensor.rst)、光照(ep_light_sensor.rst)、接触(ep_contact_sensor.rst)等均可参考同一套 API 风格
  • 类声明:MatterOccupancySensor.h
  • 类实现:MatterOccupancySensor.cpp

【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 17:23:25

【C语言】 数组

目录 1&#xff0c;数组的概念 2&#xff0c;数组的创建和初始化 3&#xff0c;数组的使用 4&#xff0c;数组的内存存储情况 5&#xff0c;sizeof 计算数组的元素个数 6&#xff0c;二维数组 7&#xff0c;二维数组的初始化和创建 8&#xff0c;二维数组的使用 9&…

作者头像 李华
网站建设 2026/9/14 17:22:31

供配电实训仿真软件:倒闸操作与故障处理全流程解析

干电气培训这些年&#xff0c;我见过太多学员第一次面对高压柜时的表情——手放在断路器分闸按钮上&#xff0c;迟迟不敢按下去。不是不知道步骤&#xff0c;而是怕按错了出大事。这种怕是对的&#xff0c;10kV开关柜一旦带负荷拉隔离开关&#xff0c;电弧瞬间就能把人灼伤&…

作者头像 李华
网站建设 2026/9/14 17:19:13

C++序列输出题全攻略:从读题到OJ提交的完整避坑指南

1. 一道短得不像话的题&#xff0c;凭什么让我交了三版才过东华OJ的基础题里有一类题属于“看着简单、做着崩溃”&#xff0c;第50题“按要求输出序列”就是典型。题面可能短到只有一句话&#xff0c;给一个整数N&#xff0c;让你按某种规则输出一串数。很多人的第一反应是&…

作者头像 李华
网站建设 2026/9/14 17:17:56

商丘做建设网站的公司3个最佳实践解决网站被黑

商丘做建设网站的公司3个最佳实践解决网站被黑 网站被黑挂马,后台密码泄露,首页瞬间变成赌博链接,这种绝望感每个运维都懂。在商丘本地,很多中小企业找 商丘做建设网站的公司 时,只盯着价格,却忽略了安全架构,结果就是养虎为患。面对这种紧急状况,盲目重装系统往往治标不治本,真正的 最佳实践…

作者头像 李华
网站建设 2026/9/14 17:10:55

多无人机动态避障路径规划与MATLAB实现

1. 项目概述&#xff1a;多无人机动态避障的工程挑战去年参与某物流园区无人机集群项目时&#xff0c;我们遇到一个典型场景&#xff1a;7台物流无人机需要在3分钟内穿越布满移动障碍物的装卸区。传统RRT算法在动态环境下频繁出现路径震荡&#xff0c;最终有3台无人机因避障超时…

作者头像 李华