Skip to content

Section 7 Sensors

Ben edited this page Nov 7, 2025 · 6 revisions

Sensors

This guide covers Matter device types for various sensors, including air quality, contact, occupancy, light, temperature, humidity, smoke/CO alarm, and water leak detectors.


Air Quality Sensor

Property Value
Device Type api.matter.deviceTypes.AirQualitySensor
Description A multi-sensor that monitors air quality, particulate matter (PM2.5 and PM10), temperature, and humidity.
Matter Specification § 7.6

Apple Home Compatibility Note: Currently, only the Air Quality cluster appears in the Apple Home app. The PM2.5, PM10, temperature, and humidity measurements are available in the Matter accessory but are not displayed by Apple Home. However, these measurements can be accessed by other Matter-compatible apps.

Clusters

This device combines multiple measurement clusters:

  1. Air Quality - Overall air quality rating
  2. PM2.5 Concentration Measurement - Fine particulate matter (≤2.5 micrometers)
  3. PM10 Concentration Measurement - Coarse particulate matter (≤10 micrometers)
  4. Temperature Measurement - Ambient temperature
  5. Relative Humidity Measurement - Relative humidity

AirQuality Cluster

Provides an overall air quality assessment.

Attributes
Attribute Type Range/Values Description
airQuality number 0-6 Overall air quality rating ¹

¹ Air Quality Values:

Value Quality Description
0 Unknown Air quality cannot be determined
1 Good Air quality is good
2 Fair Air quality is fair
3 Moderate Air quality is moderate
4 Poor Air quality is poor
5 Very Poor Air quality is very poor
6 Extremely Poor Air quality is extremely poor
Reading State
const airQuality = accessory.clusters.airQuality.airQuality
const qualityNames = ['Unknown', 'Good', 'Fair', 'Moderate', 'Poor', 'Very Poor', 'Extremely Poor']
log.info(`Air Quality: ${qualityNames[airQuality]}`)
Updating State
// Update overall air quality rating
async function updateAirQuality(quality: 0 | 1 | 2 | 3 | 4 | 5 | 6) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.AirQuality,
    { airQuality: quality }
  )

  const qualityStr = ['Unknown', 'Good', 'Fair', 'Moderate', 'Poor', 'Very Poor', 'Extremely Poor'][quality]
  log.info(`Air quality: ${qualityStr}`)
}

// Example: Set to Good
updateAirQuality(1)

Pm25ConcentrationMeasurement Cluster

Measures fine particulate matter concentration.

Attributes
Attribute Type Range/Values Description
measuredValue number 0-1000 PM2.5 concentration in µg/m³
minMeasuredValue number 0-999 Minimum measurable value
maxMeasuredValue number 1-1000 Maximum measurable value
measurementUnit number 0 Unit type (0 = µg/m³)
measurementMedium number 0 Measurement medium (0 = Air)
Updating State
// Update PM2.5 concentration
async function updatePM25(value: number) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.Pm25ConcentrationMeasurement,
    { measuredValue: value }
  )

  log.info(`PM2.5: ${value} µg/m³`)
}

// Example: 12 µg/m³ (good air quality)
updatePM25(12)

Pm10ConcentrationMeasurement Cluster

Measures coarse particulate matter concentration.

Attributes
Attribute Type Range/Values Description
measuredValue number 0-1000 PM10 concentration in µg/m³
minMeasuredValue number 0-999 Minimum measurable value
maxMeasuredValue number 1-1000 Maximum measurable value
measurementUnit number 0 Unit type (0 = µg/m³)
measurementMedium number 0 Measurement medium (0 = Air)
Updating State
// Update PM10 concentration
async function updatePM10(value: number) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.Pm10ConcentrationMeasurement,
    { measuredValue: value }
  )

  log.info(`PM10: ${value} µg/m³`)
}

// Example: 25 µg/m³ (good air quality)
updatePM10(25)

Temperature & Humidity Clusters

The Air Quality Sensor also includes TemperatureMeasurement and RelativeHumidityMeasurement clusters. See the Temperature Sensor and Humidity Sensor sections for details on these clusters.

Initial State

clusters: {
  airQuality: {
    airQuality: 1, // Good
  },
  pm25ConcentrationMeasurement: {
    measuredValue: 12,        // 12 µg/m³
    minMeasuredValue: 0,
    maxMeasuredValue: 1000,
    measurementUnit: 0,       // µg/m³
    measurementMedium: 0,     // Air
  },
  pm10ConcentrationMeasurement: {
    measuredValue: 25,        // 25 µg/m³
    minMeasuredValue: 0,
    maxMeasuredValue: 1000,
    measurementUnit: 0,       // µg/m³
    measurementMedium: 0,     // Air
  },
  temperatureMeasurement: {
    measuredValue: 2100,      // 21.00°C
    minMeasuredValue: -5000,  // -50°C
    maxMeasuredValue: 10000,  // 100°C
  },
  relativeHumidityMeasurement: {
    measuredValue: 5500,      // 55%
    minMeasuredValue: 0,
    maxMeasuredValue: 10000,  // 100%
  },
}

Handler: Air quality sensors are read-only (no handlers needed).


Contact Sensor

Property Value
Device Type api.matter.deviceTypes.ContactSensor
Description A contact sensor that detects open/closed state (e.g., door sensor, window sensor).
Matter Specification § 7.1

BooleanState Cluster

Represents the contact sensor state using a boolean value.

IMPORTANT - Inverted Semantics: The BooleanState cluster for contact sensors uses inverted logic:

  • true = Contact closed / Normal state (door/window is closed)
  • false = Contact open / Triggered state (door/window is open)

This is the opposite of intuitive expectation, so you must invert values when updating the state.

Attributes

Attribute Type Range/Values Description
stateValue boolean true, false Contact state (true=closed/normal, false=open/triggered)

Reading State

const stateValue = accessory.clusters.booleanState.stateValue
// true = closed/normal, false = open/triggered
const isOpen = !stateValue // Invert to get intuitive open/closed

Updating State

// When your physical sensor reports a state change
async function updateContactState(isOpen: boolean) {
  // IMPORTANT: Invert the value!
  // Matter BooleanState: false = open/triggered, true = closed/normal
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.BooleanState,
    { stateValue: !isOpen } // Invert!
  )

  log.info(`Contact state: ${isOpen ? 'OPEN' : 'CLOSED'}`)
}

// Example: Door opened
updateContactState(true) // Sends stateValue: false to Matter

// Example: Door closed
updateContactState(false) // Sends stateValue: true to Matter

Initial State

clusters: {
  booleanState: {
    stateValue: true,  // true = closed/normal (safe default)
  },
}

Handler: Contact sensors are read-only (no handlers needed).


Occupancy Sensor

Property Value
Device Type api.matter.deviceTypes.MotionSensor (with OccupancySensing cluster)
Description A sensor that detects occupancy/motion using PIR, ultrasonic, or physical contact methods.
Matter Specification § 7.3

Note: Matter.js API calls this device type "MotionSensor" but it's actually an Occupancy Sensor - this is how it appears in Apple Home and other Matter controllers.

OccupancySensing Cluster

Detects occupancy using various sensing methods.

Attributes

Attribute Type Range/Values Description
occupancy.occupied boolean true, false Occupancy detected (true=occupied, false=clear)
occupancySensorType number 0-2 Sensor type (0=PIR, 1=Ultrasonic, 2=Physical)
occupancySensorTypeBitmap object See below Bitmap of supported sensor types

Occupancy Sensor Type Bitmap:

{
  pir: true,              // Passive infrared
  ultrasonic: false,      // Ultrasonic
  physicalContact: false, // Physical contact
}

Reading State

const isOccupied = accessory.clusters.occupancySensing.occupancy.occupied

Updating State

// When your physical sensor detects motion/occupancy
mqttClient.on('message', async (topic, message) => {
  const detected = message.toString() === 'motion'

  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.OccupancySensing,
    { occupancy: { occupied: detected } }
  )

  log.info(`Occupancy: ${detected ? 'detected' : 'clear'}`)
})

Initial State (with PIR Sensor)

// Configure OccupancySensor with PIR feature
const OccupancySensingServer = api.matter.deviceTypes.MotionSensor.requirements.OccupancySensingServer
const OccupancySensorWithPIR = api.matter.deviceTypes.MotionSensor.with(
  OccupancySensingServer.with('PassiveInfrared'),
)

{
  deviceType: OccupancySensorWithPIR,
    clusters: {
  occupancySensing: {
    occupancy: {
      occupied: false,  // No occupancy detected initially
    },
    occupancySensorType: 0,  // PIR
      occupancySensorTypeBitmap: {
      pir: true,
        ultrasonic: false,
        physicalContact: false,
    },
  },
},
}

Handler: Occupancy sensors are read-only (no handlers needed).


Light Sensor

Property Value
Device Type api.matter.deviceTypes.LightSensor
Description A sensor that measures ambient light levels.
Matter Specification § 7.2

IlluminanceMeasurement Cluster

Measures illuminance (light level) in lux.

Attributes

Attribute Type Range/Values Description
measuredValue number 0-65534 Current light level (logarithmic scale) ¹
minMeasuredValue number 1-65533 Minimum measurable light level
maxMeasuredValue number 2-65534 Maximum measurable light level

¹ The measuredValue uses a logarithmic scale: value = 10000 × log₁₀(lux)

Value Conversion:

// Lux to Matter value
const matterValue = Math.round(10000 * Math.log10(lux))

// Matter value to Lux
const lux = 10 ** (matterValue / 10000)

Reading State

const matterValue = accessory.clusters.illuminanceMeasurement.measuredValue
const lux = 10 ** (matterValue / 10000)
log.info(`Light level: ${lux.toFixed(1)} lux`)

Updating State

// When your physical sensor reports a new light level
async function updateIlluminance(lux: number) {
  const value = Math.round(10000 * Math.log10(lux))

  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.IlluminanceMeasurement,
    { measuredValue: value }
  )

  log.info(`Illuminance: ${lux} lux`)
}

// Example: 500 lux
updateIlluminance(500) // Sends value: ~27000

Initial State

clusters: {
  illuminanceMeasurement: {
    measuredValue: 5000,   // ~3.16 lux
      minMeasuredValue: 1,   // Minimum
      maxMeasuredValue: 65534, // Maximum
  },
}

Handler: Light sensors are read-only (no handlers needed).


Temperature Sensor

Property Value
Device Type api.matter.deviceTypes.TemperatureSensor
Description A sensor that measures ambient temperature.
Matter Specification § 7.4

TemperatureMeasurement Cluster

Measures temperature in degrees Celsius.

Attributes

Attribute Type Range/Values Description
measuredValue number -27315-32767 Current temperature (hundredths of °C) ¹
minMeasuredValue number -27315-32767 Minimum measurable temperature
maxMeasuredValue number -27315-32767 Maximum measurable temperature

¹ Temperature values are in hundredths of degrees Celsius: 2100 = 21.00°C

Reading State

const tempHundredths = accessory.clusters.temperatureMeasurement.measuredValue
const celsius = tempHundredths / 100
log.info(`Temperature: ${celsius}°C`)

Updating State

// When your physical sensor reports a new temperature
async function updateTemperature(celsius: number) {
  const value = Math.round(celsius * 100)

  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.TemperatureMeasurement,
    { measuredValue: value }
  )

  log.info(`Temperature: ${celsius}°C`)
}

// Example: 21.5°C
updateTemperature(21.5) // Sends value: 2150

Initial State

clusters: {
  temperatureMeasurement: {
    measuredValue: 2100,     // 21.00°C
    minMeasuredValue: -5000, // -50.00°C
    maxMeasuredValue: 10000, // 100.00°C
  },
}

Handler: Temperature sensors are read-only (no handlers needed).


Humidity Sensor

Property Value
Device Type api.matter.deviceTypes.HumiditySensor
Description A sensor that measures relative humidity.
Matter Specification § 7.7

RelativeHumidityMeasurement Cluster

Measures relative humidity as a percentage.

Attributes

Attribute Type Range/Values Description
measuredValue number 0-10000 Current humidity (hundredths of a percent) ¹
minMeasuredValue number 0-9999 Minimum measurable humidity
maxMeasuredValue number 1-10000 Maximum measurable humidity

¹ Humidity values are in hundredths of a percent: 5500 = 55.00%

Reading State

const humidityHundredths = accessory.clusters.relativeHumidityMeasurement.measuredValue
const percent = humidityHundredths / 100
log.info(`Humidity: ${percent}%`)

Updating State

// When your physical sensor reports new humidity
async function updateHumidity(percent: number) {
  const value = Math.round(percent * 100)

  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.RelativeHumidityMeasurement,
    { measuredValue: value }
  )

  log.info(`Humidity: ${percent}%`)
}

// Example: 65.5%
updateHumidity(65.5) // Sends value: 6550

Initial State

clusters: {
  relativeHumidityMeasurement: {
    measuredValue: 5500,     // 55%
    minMeasuredValue: 0,     // 0%
    maxMeasuredValue: 10000, // 100%
  },
}

Handler: Humidity sensors are read-only (no handlers needed).


Smoke/CO Alarm

Property Value
Device Type api.matter.deviceTypes.SmokeSensor (with SmokeAlarm and CoAlarm features)
Description A combined smoke and carbon monoxide alarm sensor.
Matter Specification § 7.9

SmokeCoAlarm Cluster

Detects smoke and carbon monoxide with three alarm states.

Attributes

Attribute Type Range/Values Description
smokeState number 0-2 Smoke alarm state (0=Normal, 1=Warning, 2=Critical)
coState number 0-2 CO alarm state (0=Normal, 1=Warning, 2=Critical)
batteryAlert number 0-2 Battery level alert
deviceMuted number 0-2 Device mute status
testInProgress boolean true/false Whether self-test is running
hardwareFaultAlert boolean true/false Hardware fault detected
endOfServiceAlert number 0-2 End of service life alert
interconnectSmokeAlarm number 0-2 Interconnected smoke alarm status
interconnectCoAlarm number 0-2 Interconnected CO alarm status
contaminationState number 0-2 Sensor contamination state
smokeSensitivityLevel number 0-2 Smoke sensitivity level
expressedState number 0-10 Overall alarm state

Alarm State Values:

Value State Description
0 Normal No alarm detected
1 Warning Warning level detected
2 Critical Critical level detected

Reading State

const smokeState = accessory.clusters.smokeCoAlarm.smokeState
const coState = accessory.clusters.smokeCoAlarm.coState

const stateNames = ['Normal', 'Warning', 'Critical']
log.info(`Smoke: ${stateNames[smokeState]}, CO: ${stateNames[coState]}`)

Updating State

// Update smoke alarm state
async function updateSmokeState(state: 0 | 1 | 2) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.SmokeCoAlarm,
    { smokeState: state }
  )

  const stateStr = ['Normal', 'Warning', 'Critical'][state]
  log.info(`Smoke state: ${stateStr}`)
}

// Update CO alarm state
async function updateCOState(state: 0 | 1 | 2) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.SmokeCoAlarm,
    { coState: state }
  )

  const stateStr = ['Normal', 'Warning', 'Critical'][state]
  log.info(`CO state: ${stateStr}`)
}

// Example: Smoke detected
updateSmokeState(2) // Critical

Initial State (with Both Features)

// Configure Smoke/CO Alarm with both features
const SmokeCoAlarmServer = api.matter.deviceTypes.SmokeSensor.requirements.SmokeCoAlarmServer
const SmokeSensorWithBoth = api.matter.deviceTypes.SmokeSensor.with(
  SmokeCoAlarmServer.with('SmokeAlarm', 'CoAlarm'),
)

{
  deviceType: SmokeSensorWithBoth,
    clusters: {
  smokeCoAlarm: {
    smokeState: 0,              // Normal
    coState: 0,                 // Normal
    batteryAlert: 0,            // Normal
    deviceMuted: 0,             // Not muted
    testInProgress: false,      // No test running
    hardwareFaultAlert: false,  // No fault
    endOfServiceAlert: 0,       // Normal
    interconnectSmokeAlarm: 0,  // Normal
    interconnectCoAlarm: 0,     // Normal
    contaminationState: 0,      // Normal
    smokeSensitivityLevel: 1,   // Standard sensitivity
    expressedState: 0,          // Normal
  },
},
}

Handler: Smoke/CO alarms are read-only (no handlers needed).


Water Leak Detector

Property Value
Device Type api.matter.deviceTypes.LeakSensor
Description A sensor that detects water leaks.
Matter Specification § 7.12

BooleanState Cluster

Represents water leak detection state using a boolean value.

NOTE: Unlike contact sensors, leak detectors use standard (non-inverted) semantics:

  • false = No leak detected / Dry (normal state)
  • true = Leak detected / Wet (triggered state)

Attributes

Attribute Type Range/Values Description
stateValue boolean true, false Leak state (true=leak, false=dry)

Reading State

const leakDetected = accessory.clusters.booleanState.stateValue
log.info(`Leak: ${leakDetected ? 'DETECTED' : 'None'}`)

Updating State

// When your physical sensor reports leak state
async function updateLeakState(leakDetected: boolean) {
  await api.matter.updateAccessoryState(
    uuid,
    api.matter.clusterNames.BooleanState,
    { stateValue: leakDetected }
  )

  log.info(`Leak: ${leakDetected ? 'detected' : 'none'}`)
}

// Example: Leak detected
updateLeakState(true) // Sends stateValue: true

// Example: Leak cleared
updateLeakState(false) // Sends stateValue: false

Initial State

clusters: {
  booleanState: {
    stateValue: false,  // false = dry/normal (safe default)
  },
}

Handler: Leak sensors are read-only (no handlers needed).

Clone this wiki locally