-
-
Notifications
You must be signed in to change notification settings - Fork 0
Section 12 Robotic
This guide covers Matter device types for smart home appliances, including robotic vacuum cleaners.
| Property | Value |
|---|---|
| Device Type | api.matter.deviceTypes.RoboticVacuumCleaner |
| Description | A robotic vacuum cleaner with run modes, operational states, and cleaning modes. |
| Matter Specification | § 12.1 |
Controls the vacuum's run mode (Idle, Cleaning, etc.).
| Attribute | Type | Description |
|---|---|---|
supportedModes |
array | List of supported run modes |
currentMode |
number | Current run mode |
Common Run Mode Tags:
| Tag Value | Name | Description |
|---|---|---|
| 16384 | Idle | Vacuum is idle/docked |
| 16385 | Cleaning | Vacuum is cleaning |
| 16386 | Mapping | Vacuum is mapping the space |
Controls the vacuum's cleaning mode (Vacuum, Mop, etc.).
| Attribute | Type | Description |
|---|---|---|
supportedModes |
array | List of supported clean modes |
currentMode |
number | Current clean mode |
Common Clean Mode Tags:
| Tag Value | Name | Description |
|---|---|---|
| 16384 | DeepClean | Deep cleaning mode |
| 16385 | Vacuum | Vacuum only mode |
| 16386 | Mop | Mop only mode |
Reports the vacuum's operational state and provides control commands.
| Attribute | Type | Description |
|---|---|---|
operationalStateList |
array | List of supported operational states |
operationalState |
number | Current operational state ID |
Common Operational State IDs:
| State ID | State | Description |
|---|---|---|
| 0 | Stopped | Vacuum is stopped |
| 1 | Running | Vacuum is actively cleaning |
| 2 | Paused | Vacuum is paused |
| 3 | Error | Vacuum encountered an error |
| 64 | SeekingCharger | Vacuum is seeking its charging dock |
| 65 | Charging | Vacuum is charging on the dock |
| 66 | Docked | Vacuum is docked and fully charged |
| 67 | EmptyingDustBin | Vacuum is emptying dust bin (on dock) |
| 68 | CleaningMop | Vacuum is cleaning mop (on dock) |
| 69 | FillingWaterTank | Vacuum is filling water tank |
| 70 | UpdatingMaps | Vacuum is processing map updates |
Note: States 67-70 are maintenance states added in Matter 1.4.2. These represent automatic maintenance operations typically performed when the vacuum returns to its dock.
Controls room/zone selection for targeted cleaning.
| Attribute | Type | Description |
|---|---|---|
supportedMaps |
array | List of supported maps (can be empty) |
supportedAreas |
array | List of supported areas/rooms |
selectedAreas |
array | Currently selected area IDs for cleaning |
currentArea |
number | Area ID currently being cleaned (null if none) |
progress |
array | Cleaning progress per area |
Area Definition:
Each area in supportedAreas has this structure:
{
areaId: 0,
mapId: null, // must be null when supportedMaps is empty
areaInfo: {
locationInfo: {
locationName: 'Living Room',
floorNumber: 0,
areaType: 7, // AreaNamespaceTag (e.g., 7 = LivingRoom)
},
landmarkInfo: null,
},
}Reports battery status, charge level, and remaining percentage.
| Attribute | Type | Description |
|---|---|---|
status |
number | Power source status (0 = Active) |
order |
number | Priority order (0 = Primary) |
description |
string | Power source description (e.g., "Battery") |
batPercentRemaining |
number | Battery percentage (0-200, where 200 = 100%) |
batChargeLevel |
number | Charge level indicator |
batReplaceability |
number | Whether battery is replaceable |
Battery Charge Levels:
| Level | Name | Description |
|---|---|---|
| 0 | Ok | Battery charge is sufficient |
| 1 | Warning | Battery charge is low |
| 2 | Critical | Battery charge is critical |
Battery Replaceability:
| Value | Name | Description |
|---|---|---|
| 0 | Unspecified | Replaceability not specified |
| 1 | Not replaceable | Battery cannot be replaced |
| 2 | User replaceable | User can replace battery |
| 3 | Factory replaceable | Requires factory replacement |
Note: batPercentRemaining uses 0.5% increments, where 200 = 100%. For example:
- 200 = 100%
- 100 = 50%
- 50 = 25%
- 0 = 0%
const runMode = accessory.clusters.rvcRunMode.currentMode
const cleanMode = accessory.clusters.rvcCleanMode.currentMode
const opState = accessory.clusters.rvcOperationalState.operationalState
const battery = accessory.clusters.powerSource.batPercentRemaining
const runModes = ['Idle', 'Cleaning']
const cleanModes = ['Vacuum', 'Mop']
const opStates = ['Stopped', 'Running', 'Paused', 'Error']
const batteryPercent = (battery / 2).toFixed(1) // Convert to percentage
log.info(`Run: ${runModes[runMode]}, Clean: ${cleanModes[cleanMode]}, State: ${opStates[opState]}, Battery: ${batteryPercent}%`)// Handler types are automatically inferred from ClusterHandlerMap
handlers: {
rvcRunMode: {
/**
* Called when user changes run mode via Home app.
* Start/stop is controlled through run mode changes (Idle ↔ Cleaning).
*/
changeToMode: async (request) => {
const { newMode } = request
const modeStr = ['Idle', 'Cleaning'][newMode] || 'Unknown'
log.info(`Changing run mode to: ${modeStr}`)
await myVacuumAPI.setRunMode(newMode)
// Update operational state based on run mode
if (newMode === 1) {
// Starting to clean — set operational state to Running
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: 1 } // Running
)
} else if (newMode === 0) {
// Switching to Idle — return to dock
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: 0 } // Stopped
)
}
// State automatically updated by Homebridge for the run mode cluster
},
},
rvcCleanMode: {
/**
* Called when user changes clean mode via Home app
*/
changeToMode: async (request) => {
const { newMode } = request
const modeStr = ['Vacuum', 'Mop'][newMode] || 'Unknown'
log.info(`Changing clean mode to: ${modeStr}`)
await myVacuumAPI.setCleanMode(newMode)
// State automatically updated by Homebridge
},
},
// Note: rvcOperationalState only supports pause, resume, and goHome handlers.
// Start/stop is controlled through rvcRunMode.changeToMode instead.
rvcOperationalState: {
/**
* Called when user pauses the vacuum
*/
pause: async () => {
log.info('Pausing vacuum')
await myVacuumAPI.pause()
// Update state to Paused (2)
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: 2 }
)
},
/**
* Called when user resumes the vacuum
*/
resume: async () => {
log.info('Resuming vacuum')
await myVacuumAPI.resume()
// Update state to Running (1)
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: 1 }
)
},
/**
* Called when user sends the vacuum home
*/
goHome: async () => {
log.info('Sending vacuum home')
await myVacuumAPI.goHome()
// Update to seeking charger, then charging, then docked
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: 64 } // SeekingCharger
)
},
},
serviceArea: {
/**
* Called when user selects areas/rooms to clean
*/
selectAreas: async (request) => {
const { newAreas } = request
const areaNames = newAreas.map((id: number) =>
['Living Room', 'Kitchen', 'Bedroom', 'Bathroom'][id] || `Area ${id}`
)
log.info(`Selecting areas: ${areaNames.join(', ')}`)
await myVacuumAPI.selectAreas(newAreas)
},
/**
* Called when user skips a specific area during cleaning
*/
skipArea: async (request) => {
const { skippedArea } = request
log.info(`Skipping area: ${skippedArea}`)
await myVacuumAPI.skipArea(skippedArea)
},
},
}// Update operational state
async function updateOperationalState(state: number) {
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcOperationalState,
{ operationalState: state }
)
const states = ['Stopped', 'Running', 'Paused', 'Error']
log.info(`Operational state: ${states[state]}`)
}
// Update run mode
async function updateRunMode(mode: number) {
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcRunMode,
{ currentMode: mode }
)
const modes = ['Idle', 'Cleaning']
log.info(`Run mode: ${modes[mode]}`)
}
// Update clean mode
async function updateCleanMode(mode: number) {
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.RvcCleanMode,
{ currentMode: mode }
)
const modes = ['Vacuum', 'Mop']
log.info(`Clean mode: ${modes[mode]}`)
}
// Update battery status
async function updateBatteryStatus(percent: number, chargeLevel: number) {
const batPercentRemaining = percent * 2 // Convert percentage to 0-200 scale
await api.matter.updateAccessoryState(
uuid,
api.matter.clusterNames.PowerSource,
{
batPercentRemaining,
batChargeLevel: chargeLevel // 0 = Ok, 1 = Warning, 2 = Critical
}
)
const levels = ['Ok', 'Warning', 'Critical']
log.info(`Battery: ${percent}% (${levels[chargeLevel]})`)
}
// Update selected areas
async function updateSelectedAreas(areaIds: number[]) {
await api.matter.updateAccessoryState(
uuid,
'serviceArea',
{ selectedAreas: areaIds }
)
}
// Update current area being cleaned
async function updateCurrentArea(areaId: number | null) {
await api.matter.updateAccessoryState(
uuid,
'serviceArea',
{ currentArea: areaId }
)
}Initial State:
clusters: {
rvcRunMode: {
supportedModes: [
{ label: 'Idle', mode: 0, modeTags: [{ value: 16384 }] },
{ label: 'Cleaning', mode: 1, modeTags: [{ value: 16385 }] },
],
currentMode: 0, // Idle
},
rvcCleanMode: {
supportedModes: [
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
],
currentMode: 0, // Vacuum
},
rvcOperationalState: {
operationalStateList: [
{ operationalStateId: 0 }, // stopped
{ operationalStateId: 1 }, // running
{ operationalStateId: 2 }, // paused
{ operationalStateId: 3 }, // error
],
operationalState: 0, // Stopped
},
powerSource: {
status: 0, // 0 = Active
order: 0, // Primary power source
description: 'Battery',
batPercentRemaining: 200, // 200 = 100% (use percent * 2)
batChargeLevel: 0, // 0 = Ok, 1 = Warning, 2 = Critical
batReplaceability: 1, // 0 = Unspecified, 1 = Not replaceable, 2 = User replaceable, 3 = Factory replaceable
},
serviceArea: {
supportedMaps: [], // empty - no map features
supportedAreas: [
{
areaId: 0,
mapId: null, // must be null when supportedMaps is empty
areaInfo: {
locationInfo: { locationName: 'Living Room', floorNumber: 0, areaType: 7 },
landmarkInfo: null,
},
},
{
areaId: 1,
mapId: null,
areaInfo: {
locationInfo: { locationName: 'Kitchen', floorNumber: 0, areaType: 10 },
landmarkInfo: null,
},
},
],
selectedAreas: [0, 1], // all areas selected by default
},
}Publishing:
const accessories = [
{
UUID: api.matter.uuid.generate('robot-vacuum'),
displayName: 'Robot Vacuum',
deviceType: api.matter.deviceTypes.RoboticVacuumCleaner,
// ... configuration
}
]
// Register using the standard method
await api.matter.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessories)QR Codes:
Robotic vacuum cleaners registered via registerPlatformAccessories() receive their own unique QR code for pairing, separate from the main bridge QR code.