物理开关 Cluster(Switch)

Cluster ID: 0x003B  |  所在 Endpoint: 通常在 Endpoint 1(功能端点)

Switch Cluster 描述的是物理输入设备 —— 墙壁上的拨动开关、门铃按钮、调光旋钮等。 它不控制任何输出(开灯、关灯那是 OnOff Cluster 的事),而是把用户的物理操作转化为事件, 由绑定的目标设备或自动化规则来决定具体动作。

Switch ≠ OnOff

容易混淆的两个 Cluster:Switch(0x003B)是物理输入设备,负责上报「用户按了什么」; OnOff(0x0006)是输出控制,负责执行「设备开还是关」。 一个墙壁开关面板通常同时包含两者 —— Switch 检测按压动作,OnOff 执行开关控制。 但 Switch Cluster 本身没有任何命令,它是纯粹的事件源。

事件驱动模型

Switch Cluster 是 Matter 中最典型的事件驱动 Cluster。 它没有命令(不接受外部指令),所有信息通过事件上报。 控制器(手机、Hub)需要订阅事件来感知用户操作,而不是轮询属性变化。

Feature 位图

Switch Cluster 的 Feature Map 非常重要 —— 它决定了设备是哪种类型的开关,以及会上报哪些事件。 设备必须声明 LS(锁定开关)或 MS(瞬时开关)中的一个,且两者互斥。

Bit 0
LS(Latching Switch) 锁定式开关 —— 拨到某个位置后保持不动(如传统墙壁拨动开关)。与 MS 互斥
Bit 1
MS(Momentary Switch) 瞬时开关 —— 按下后松手会自动回弹(如按钮、门铃)。与 LS 互斥
Bit 2
MSR(Momentary Switch Release) 松手检测 —— 支持检测按钮释放动作。依赖 MS
Bit 3
MSL(Momentary Switch Long Press) 长按检测 —— 支持区分短按和长按。依赖 MS + MSR
Bit 4
MSM(Momentary Switch Multi Press) 多次按压 —— 支持双击、三击等连续按压检测。依赖 MS + MSR
Feature 依赖关系

LS 和 MS 二选一,不能同时声明。
MSR 依赖 MS(只有瞬时开关才有「松手」概念)。
MSL 和 MSM 都依赖 MS + MSR(需要精确的按下/释放时机才能判断长按或连击)。

Feature 组合示例

设备类型 Feature 值 启用的 Feature 支持的事件
传统墙壁拨动开关 0x01 LS SwitchLatched
简单按钮 0x06 MS + MSR InitialPress, ShortRelease
支持长按的按钮 0x0E MS + MSR + MSL InitialPress, ShortRelease, LongPress, LongRelease
全功能按钮(长按 + 连击) 0x1E MS + MSR + MSL + MSM 全部瞬时事件

属性详解

Switch Cluster 只有 3 个属性,都是只读的。开关的核心信息通过事件上报,属性主要用于描述设备能力。

ID 名称 类型 必选 说明
0x0000 NumberOfPositions uint8 是 开关的位置总数。最小值为 2。普通开关是 2(开/关),多档旋钮可以更多
0x0001 CurrentPosition uint8 是 当前所在位置,范围 0 ~ NumberOfPositions - 1。对于锁定式开关,这个值在拨动后持久保持;对于瞬时开关,按下时变化、松手后可能回到 0
0x0002 MultiPressMax uint8 MSM 设备支持的最大连续按压次数。例如值为 3 表示最多识别三连击。仅在启用 MSM Feature 时存在
位置编号从 0 开始

位置编号从 0 开始。一个两位拨动开关的位置是 0 和 1,不是 1 和 2。 如果是一个 4 档旋钮,位置就是 0、1、2、3。

事件详解(Events)

事件是 Switch Cluster 的核心。所有用户操作都通过事件上报给控制器。 不同 Feature 组合决定设备会上报哪些事件。点击下方表格中的事件 ID 可跳转到详细说明。

ID 名称 所需 Feature 说明
0x00 SwitchLatched LS 锁定式开关拨到新位置
0x01 InitialPress MS 瞬时按钮被按下
0x02 LongPress MS + MSL 按钮被长按(超过阈值未松手)
0x03 ShortRelease MS + MSR 按钮短按后松手
0x04 LongRelease MS + MSL 按钮长按后松手
0x05 MultiPressOngoing MS + MSM 连续按压进行中(每次按下都上报)
0x06 MultiPressComplete MS + MSM 连续按压结束(上报总次数)

SwitchLatched —— 锁定开关拨动(0x00)

当锁定式开关(Latching Switch)被拨到一个新位置时触发。 这是 LS 类型设备唯一会上报的事件 —— 简单直接:拨了就报,报完就没了。

字段类型说明
NewPosition uint8 开关被拨到的新位置
典型场景

传统墙壁拨动开关:用户把开关从「下」拨到「上」,设备上报 SwitchLatched {'{ NewPosition: 1 }'}。 控制器收到后通过绑定关系向灯发送 On 命令。

InitialPress —— 按下(0x01)

瞬时按钮被按下的瞬间触发。这是所有瞬时开关(MS)操作序列的起点 —— 无论后续是短按、长按还是连击,都从 InitialPress 开始。

字段类型说明
NewPosition uint8 按下后的位置(通常为 1)
典型场景

用户按下门铃按钮,设备立即上报 InitialPress {'{ NewPosition: 1 }'}。 控制器可以在这个时刻就触发门铃响铃,不用等松手。

LongPress —— 长按(0x02)

按钮被持续按住,超过设备内部的长按阈值后触发。 在 InitialPress 之后、松手之前上报。需要 MSL Feature。

字段类型说明
NewPosition uint8 按住时的位置(与 InitialPress 的 NewPosition 一致)
典型场景

调光按钮:短按切换开关,长按开始调亮度。 用户按住不放,收到 LongPress 后控制器开始持续调整灯的亮度(通过 LevelControl Cluster 的 MoveWithOnOff 命令), 直到收到 LongRelease 时停止调整。

ShortRelease —— 短按松手(0x03)

按钮在触发 LongPress 之前被松开时触发(即:这是一次短按)。 需要 MSR Feature。

字段类型说明
PreviousPosition uint8 按下时的位置(即松手前的位置)
注意字段名

ShortRelease 和 LongRelease 的字段是 PreviousPosition(松手前的位置), 而 InitialPress 和 LongPress 的字段是 NewPosition(按下后的位置)。 虽然数值通常相同,但语义不同 —— 一个描述「按下去到哪」,一个描述「从哪松开」。

典型场景

智能按钮:收到 ShortRelease 确认这是一次短按,执行对应的短按动作(如 Toggle 开关灯)。 如果启用了 MSM Feature,设备会等待判断是否有后续按压(连击),此时 ShortRelease 可能不会立即触发。

LongRelease —— 长按松手(0x04)

在 LongPress 触发之后松手时触发(即:长按结束)。 需要 MSL Feature。

字段类型说明
PreviousPosition uint8 长按时的位置(即松手前的位置)
典型场景

调光按钮长按松手:收到 LongRelease 后,控制器停止亮度调整(发送 StopWithOnOff 命令),灯保持在当前亮度。

MultiPressOngoing —— 连续按压进行中(0x05)

在连续快速按压过程中,每次按下都会触发此事件,携带当前已累计的按压次数。 需要 MSM Feature。

字段类型说明
NewPosition uint8 按下后的位置
CurrentNumberOfPressesCounted uint8 到目前为止已累计的按压次数(从 2 开始,因为第一次按压是 InitialPress)
典型场景

用户快速三连击按钮。事件序列:

  1. InitialPress {'{ NewPosition: 1 }'} —— 第一次按下
  2. MultiPressOngoing {'{ NewPosition: 1, CurrentNumberOfPressesCounted: 2 }'} —— 第二次按下
  3. MultiPressOngoing {'{ NewPosition: 1, CurrentNumberOfPressesCounted: 3 }'} —— 第三次按下
  4. MultiPressComplete {'{ PreviousPosition: 1, TotalNumberOfPressesCounted: 3 }'} —— 连击结束

控制器通常等 MultiPressComplete 再执行动作,而不是对每个 Ongoing 都响应。

MultiPressComplete —— 连续按压结束(0x06)

连续按压结束后触发,携带最终的总按压次数。这是控制器判断用户意图的关键事件 —— 根据总次数决定执行什么动作(单击、双击、三击等)。 需要 MSM Feature。

字段类型说明
PreviousPosition uint8 按压时的位置
TotalNumberOfPressesCounted uint8 总按压次数。值为 1 表示单击,2 表示双击,以此类推。最大值不超过 MultiPressMax
TotalNumberOfPressesCounted = 0 的特殊含义

如果 TotalNumberOfPressesCounted 为 0,表示这次连续按压无效 (例如按压次数超过了 MultiPressMax,或者设备判定为误触)。控制器收到 0 时不应执行任何动作。

典型场景

Aqara 无线按钮:单击开灯、双击切换场景、三击关闭所有灯。 控制器等收到 MultiPressComplete 后,根据 TotalNumberOfPressesCounted 的值分发不同自动化动作。

事件序列对比

不同操作方式下的事件上报顺序:

操作 事件序列
拨动(LS) SwitchLatched
短按(MS+MSR) InitialPress → ShortRelease
长按(MS+MSR+MSL) InitialPress → LongPress → LongRelease
双击(MS+MSR+MSM) InitialPress → MultiPressOngoing(2) → MultiPressComplete(2)
单击(MS+MSR+MSM,等待后确认) InitialPress → MultiPressComplete(1)

示例数据

一个支持长按和双击的智能按钮(Feature: MS+MSR+MSL+MSM)的属性读取结果:

{
  // --- 开关位置 ---
  "0x0000": 2,              // NumberOfPositions = 2(两个位置,如常见的上/下拨动开关)
  "0x0001": 0,              // CurrentPosition = 0(当前处于位置 0)

  // --- 多次按压 ---
  "0x0002": 3               // MultiPressMax = 3(最多识别 3 连按)
}

事件订阅与接收示例

订阅 Switch Cluster 的事件,以及收到事件时的数据格式:

// 事件订阅示例 —— 订阅 Switch Cluster 的所有事件
{
  "subscribeRequest": {
    "eventRequests": [{
      "endpoint": 1,
      "cluster": "0x003B"    // Switch Cluster
    }],
    "minInterval": 0,
    "maxInterval": 60
  }
}

// 收到的 InitialPress 事件
{
  "eventPath": {
    "endpoint": 1,
    "cluster": "0x003B",
    "event": "0x01"          // InitialPress
  },
  "eventData": {
    "NewPosition": 1         // 按下后的位置
  }
}

// 收到的 MultiPressComplete 事件
{
  "eventPath": {
    "endpoint": 1,
    "cluster": "0x003B",
    "event": "0x06"          // MultiPressComplete
  },
  "eventData": {
    "PreviousPosition": 1,
    "TotalNumberOfPressesCounted": 2  // 总共按了 2 次(双击)
  }
}
开发提示

Switch Cluster 的属性很少,核心价值在事件。开发时重点关注:

  • 先读 FeatureMap (0xFFFC) 判断设备支持哪些操作模式
  • 订阅事件而不是轮询 CurrentPosition
  • 如果支持 MSM,读取 MultiPressMax 知道最多几连击
  • 对于支持多种操作的按钮,建议在 UI 中提示用户可配置单击/双击/长按的动作

常见场景

场景 1:墙壁拨动开关(Latching Switch)

设备:传统上下拨动式墙壁开关,Feature = LS(0x01)

  1. 设备声明 NumberOfPositions = 2(上/下两个位置)
  2. 用户把开关从下拨到上,设备上报 SwitchLatched {'{ NewPosition: 1 }'}
  3. 控制器通过绑定关系找到对应的灯,发送 On 命令
  4. 用户把开关从上拨到下,设备上报 SwitchLatched {'{ NewPosition: 0 }'}
  5. 控制器发送 Off 命令,灯关闭

这种开关最简单 —— 一个事件、一个动作,没有长按和连击的概念。开关位置和灯的状态是物理对应的。

场景 2:调光旋钮 / 调光按钮(Dimmer)

设备:带按压功能的旋钮或调光按钮,Feature = MS + MSR + MSL(0x0E)

  1. 用户短按:收到 InitialPress → ShortRelease,控制器执行 Toggle(切换开关)
  2. 用户长按:
    • 收到 InitialPress —— 暂不动作,等后续事件
    • 收到 LongPress —— 开始连续调亮度(发送 MoveWithOnOff 命令)
    • 收到 LongRelease —— 停止调亮度(发送 StopWithOnOff 命令)

关键设计:不要在 InitialPress 时就执行 Toggle,否则长按也会先触发一次开关切换。 正确做法是等 ShortRelease 或 LongPress 再决定动作。

场景 3:多功能无线按钮(Multi Press)

设备:Aqara / Eve 等无线智能按钮,Feature = MS + MSR + MSL + MSM(0x1E),MultiPressMax = 3

  1. 单击(等待超时后确认):InitialPress → MultiPressComplete(1) → 执行动作 A(如开灯)
  2. 双击:InitialPress → MultiPressOngoing(2) → MultiPressComplete(2) → 执行动作 B(如切换场景)
  3. 三击:InitialPress → MultiPressOngoing(2) → MultiPressOngoing(3) → MultiPressComplete(3) → 执行动作 C(如全屋关灯)
  4. 长按:InitialPress → LongPress → LongRelease → 执行动作 D(如进入配对模式)

在 App 中,可以让用户自定义每种操作对应的自动化动作,类似 Apple HomeKit 的按钮配置界面。

注意:单击的确认有延迟 —— 设备要等一小段时间确认没有后续按压才上报 MultiPressComplete(1)。 这是为了区分单击和双击的第一下,用户能感知到轻微的响应延迟。