Guida al dispositivo termostato per Android

Il tipo di dispositivo Termostato può essere implementato utilizzando diversi tratti dell'API Home, ma il tratto principale è Thermostat. Di seguito sono riportati i tratti obbligatori e facoltativi per i termostati.

Tipo di dispositivo delle API Home Tratti App di esempio Kotlin Caso d'uso

Termostato

ThermostatDevice

home.matter.0000.types.0301

Un dispositivo in grado di avere sensori integrati o separati per temperatura, umidità o occupazione e che consente di impostare la temperatura desiderata. Un termostato è in grado di inviare notifiche relative ai requisiti di riscaldamento e/o raffreddamento a un'unità di riscaldamento/raffreddamento (ad esempio, un ventilatore interno) o è in grado di includere un meccanismo per controllare direttamente un'unità di riscaldamento o raffreddamento.

Tratti richiesti
     matter Identify
     matter Thermostat

Tratti facoltativi
     matter ThermostatUserInterfaceConfiguration
     google ExtendedThermostat
Termostato

Supporto dell'API Automation

I seguenti tratti ed elementi del termostato sono supportati nell'API Automation.

Tratto Tipo di caratteristica Tipo di elemento Elemento
Termostato matter Comando SetpointRaiseLower
Termostato matter Attributo activePresetHandle
Termostato matter Attributo localTemperature
Termostato matter Attributo occupancy
Termostato matter Attributo occupiedCoolingSetpoint
Termostato matter Attributo occupiedHeatingSetpoint
Termostato matter Attributo outdoorTemperature
Termostato matter Attributo setpointChangeSource
Termostato matter Attributo systemMode
Termostato matter Attributo temperatureSetpointHold
Termostato matter Attributo temperatureSetpointHoldDuration
Termostato matter Attributo thermostatRunningMode
Termostato matter Attributo thermostatRunningState
Termostato matter Attributo unoccupiedCoolingSetpoint
Termostato matter Attributo unoccupiedHeatingSetpoint
ExtendedThermostat google Attributo activePresetHandle
ExtendedThermostat google Attributo activeRemoteTemperatureSensorIds
ExtendedThermostat google Attributo averageLocalTemperature
ExtendedThermostat google Attributo extendedRunningMode
ExtendedThermostat google Attributo extendedSystemMode

Ottenere la temperatura ambiente

Ottenere la temperatura ambiente utilizzando Termostato

Per ottenere la temperatura ambiente del termostato utilizzando il tratto Thermostat, leggi l'attributo localTemperature.

API Device

// Get the ambient temperature
val thermostat = home.devices().list().first { device -> device.has(Thermostat) }

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat
    .type(ThermostatDevice)
    .mapNotNull { it.standardTraits.thermostat }
    .distinctUntilChanged()

val localTempFlow = thermostatTraitFlow.mapNotNull { it?.localTemperature }

API Automation

val automation = automation {
  sequential {
    val starterNode = starter<_>(thermostat, ThermostatDevice, Thermostat)

    // If the temperature is higher than 35C...
    // `localTemperature` is in one hundredth of a degree Celsius.
    condition { expression = starterNode.localTemperature greaterThan 3500 }

    // ...and the automation hasn't been run for at least an hour...
    suppressFor(Duration.ofHours(1))

    // ...broadcast a message
    action(speaker, SpeakerDevice) {
      command(AssistantBroadcast.broadcast("It's very hot outside."))
    }
  }
}

Ottenere la temperatura ambiente utilizzando TemperatureMeasurement

Per ottenere la temperatura ambiente del termostato utilizzando il tratto TemperatureMeasurement, leggi l'attributo measuredValue.

API Device

val temperatureTraitFlow: Flow<TemperatureMeasurement?> =
  thermostat
    .type(TemperatureSensorDevice)
    .map { it.standardTraits.temperatureMeasurement }
    .distinctUntilChanged()

val localTemp: Short? = temperatureTraitFlow.first()?.measuredValue

API Automation

val automation = automation {
  sequential {
    val temperature = starter<_>(thermostat, ThermostatDevice, TemperatureMeasurement)
    val stateReaderNode = stateReader<_>(light, DimmableLightDevice, OnOff)
    condition() {
      val expr1 = temperature.measuredValue greaterThanOrEquals 3500
      val expr2 = stateReaderNode.onOff equals true
      expression = expr1 and expr2
    }
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}

Ottenere la temperatura media utilizzando ExtendedThermostat

Per ottenere la temperatura media di più sensori, leggi l'attributo ExtendedThermostat della caratteristica averageLocalTemperature.

API Device

// Get the average temperature
val thermostat = home.devices().list().first { device -> device.has(TemperatureSensorDevice) }

val temperatureTraitFlow: Flow<TemperatureMeasurement?> =
  thermostat
    .type(TemperatureSensorDevice)
    .map { it.standardTraits.temperatureMeasurement }
    .distinctUntilChanged()

val localTemp: Short? = temperatureTraitFlow.first()?.measuredValue

API Automation

val automation = automation {
  sequential {
    val temperature = starter<_>(thermostat, ThermostatDevice, ExtendedThermostat)
    val stateReaderNode = stateReader<_>(light, DimmableLightDevice, OnOff)
    //  if the average temperature is >= 35C
    condition() {
      val expr1 = temperature.averageLocalTemperature greaterThanOrEquals 3500
      val expr2 = stateReaderNode.onOff equals true
      expression = expr1 and expr2
    }
    // Turn on the light
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}

Ottenere l'umidità ambientale

Per ottenere l'umidità ambientale del termostato utilizzando il tratto RelativeHumidityMeasurement, leggi l'attributo measuredValue.

API Device

// Get the ambient humidity

val humidityTraitFlow: Flow<RelativeHumidityMeasurement?> =
  humiditySensingThermostat
    .type(HumiditySensorDevice)
    .map { it.standardTraits.relativeHumidityMeasurement }
    .distinctUntilChanged()

val localHumidity: UShort? = humidityTraitFlow.first()?.measuredValue

API Automation

val automation = automation {
  sequential {
    val humidity = starter<_>(thermostat, HumiditySensorDevice, RelativeHumidityMeasurement)
    val stateReaderNode = stateReader<_>(light, DimmableLightDevice, OnOff)
    // if the ambient humidity is >= 80%
    condition() {
      val expr1 = (humidity.measuredValue greaterThanOrEquals 80u)
      val expr2 = (stateReaderNode.onOff equals true)
      expression = expr1 and expr2
    }
    // Turn on the light
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}

Seleziona la scala di temperatura visualizzata

Per modificare l'unità di misura della temperatura utilizzata per il display del termostato, imposta l'attributo ThermostatUserInterfaceConfigurationTrait di temperatureDisplayMode su TemperatureDisplayModeEnum.Celsius o TemperatureDisplayModeEnum.Fahrenheit.

API Device

// Set the displayed temperature scale to Fahrenheit
val uiConfig =
  home
    .devices()
    .list()
    .filter { device -> device.has(ThermostatUserInterfaceConfiguration) }
    .first()

val uiConfigTraitFlow: Flow<ThermostatUserInterfaceConfiguration?> =
  uiConfig
    .type(ThermostatDevice)
    .map { it.standardTraits.thermostatUserInterfaceConfiguration }
    .distinctUntilChanged()

val uiConfigTrait: ThermostatUserInterfaceConfiguration = uiConfigTraitFlow.first()!!

if (
  uiConfigTrait.supports(ThermostatUserInterfaceConfiguration.Attribute.temperatureDisplayMode)
) {
  val unused =
    uiConfigTrait.update { setTemperatureDisplayMode(TemperatureDisplayModeEnum.Fahrenheit) }
}

API Automation

val automation = automation {
  isActive = true
  sequential {
    val stateReaderNode =
      stateReader<_>(thermostat, ThermostatDevice, ThermostatUserInterfaceConfiguration)

    // When someone says "Show the temperature in Fahrenheit",
    val unused =
      starter<_>(structure, VoiceStarter.OkGoogleEvent) {
        parameter(VoiceStarter.OkGoogleEvent.query("Show the temperature in Fahrenheit"))
      }
    // if the temperature isn't being shown in Fahrenheit
    condition() {
      expression =
        stateReaderNode.temperatureDisplayMode notEquals TemperatureDisplayModeEnum.Fahrenheit
    }
    // display the current temperature using Fahrenheit
    action(thermostat, ThermostatDevice) {
      update(ThermostatUserInterfaceConfiguration) {
        setTemperatureDisplayMode(TemperatureDisplayModeEnum.Fahrenheit)
      }
    }
  }
}

Cambiare la modalità di funzionamento

Il termostato può essere limitato a determinate modalità di funzionamento, definite da ThermostatTrait.SystemModeEnum, impostando l'attributo ThermostatTrait.Attributes.systemMode, i cui valori sono definiti da ThermostatTrait.Attributes.SystemModeEnum.

API Device

val thermostatDevice = structure.devices().list().first { device -> device.has(Thermostat) }

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val thermostatTrait: Thermostat = thermostatTraitFlow.first()!!

// Set the system mode to Auto
if (thermostatTrait.supports(Thermostat.Attribute.systemMode)) {
  val unused = thermostatTrait.update { setSystemMode(SystemModeEnum.Auto) }
}

API Automation

val automation = automation {
  isActive = true
  // When the door lock state changes
  sequential {
    val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent)
    val stateReaderNode = stateReader<_>(thermostat, ThermostatDevice, SimplifiedThermostat)

    // if the door is unlocked and the thermostat is in Eco mode
    condition() {
      val expr1 = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock)
      val expr2 = (stateReaderNode.systemMode equals SimplifiedThermostatSystemModeEnum.Eco)
      expression = expr1 and expr2
    }

    // Set the thermostat to Auto mode
    action(thermostat, ThermostatDevice) {
      command(SimplifiedThermostat.setSystemMode(SimplifiedThermostatSystemModeEnum.Auto))
    }
  }
}

Quando il termostato è impostato su SystemModeEnum.Auto, è possibile leggere ulteriori informazioni sulla modalità di funzionamento del termostato da ThermostatTrait.Attributes.thermostatRunningMode che viene compilato con i valori di ThermostatRunningModeEnum.

API Device

// Get the current thermostat running mode

val runningModeTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val runningMode: ThermostatTrait.ThermostatRunningModeEnum? =
  runningModeTraitFlow.first()?.thermostatRunningMode

API Automation

val automation = automation {
  isActive = true
  sequential {
    val stateReaderNode = stateReader<_>(thermostat, ThermostatDevice, Thermostat)
    // at 10:00am
    val unused =
      starter<_>(structure, Time.ScheduledTimeEvent) {
        parameter(Time.ScheduledTimeEvent.clockTime(LocalTime.of(10, 0, 0, 0)))
      }

    // if the thermostat is in Auto mode and is currently cooling
    condition() {
      val expr1 = (stateReaderNode.systemMode equals ThermostatTrait.SystemModeEnum.Auto)
      val expr2 =
        (stateReaderNode.thermostatRunningMode equals
          ThermostatTrait.ThermostatRunningModeEnum.Cool)
      expression = expr1 and expr2
    }
    // announce that it's in Cool mode
    action(structure) {
      command(AssistantBroadcast.broadcast("The thermostat is currently running in Cool mode."))
    }
  }
}

SimplifiedThermostatTrait è progettato per semplificare il processo di impostazione della modalità di funzionamento nelle automazioni. Per modificare la modalità di funzionamento del termostato utilizzando SimplifiedThermostatTrait, utilizza SetSystemModeCommand, i cui valori sono definiti da SimplifiedThermostatTrait.SystemModeEnum.

Questa caratteristica è disponibile solo per l'utilizzo con l'API Automation.

API Automation

val automation = automation {
  isActive = true

  sequential {
    // When the presence state changes...
    val starterNode = starter<_>(structure, AreaPresenceState)
    // ...and if the area is unoccupied...
    condition() {
      expression = starterNode.presenceState equals PresenceState.PresenceStateVacant
    }
    // Set the thermostat to Eco mode
    action(thermostat, ThermostatDevice) {
      command(SimplifiedThermostat.setSystemMode(SimplifiedThermostatSystemModeEnum.Eco))
    }
  }
}

Per determinare le modalità di funzionamento di un termostato, leggi ThermostatTrait.Attributes.controlSequenceOfOperation, i cui valori sono determinati da ThermostatTrait.ControlSequenceOfOperationEnum.

API Device

// Get the controlSequenceOfOperation
val standardTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val controlSequenceOfOperation: ThermostatTrait.ControlSequenceOfOperationEnum? =
  standardTraitFlow.first()?.controlSequenceOfOperation

API Automation

val automation = automation {
  isActive = true
  sequential {
    val stateReaderNode = stateReader<_>(thermostat, ThermostatDevice, Thermostat)
    // When someone says "Switch to cool mode",
    val unused =
      starter<_>(structure, VoiceStarter.OkGoogleEvent) {
        parameter(VoiceStarter.OkGoogleEvent.query("Switch to cool mode"))
      }
    // if the thermostat is capable of operating in Cool mode,
    condition() {
      val expr1 =
        stateReaderNode.controlSequenceOfOperation notEquals
          ControlSequenceOfOperationEnum.HeatingOnly
      val expr2 =
        stateReaderNode.controlSequenceOfOperation notEquals
          ControlSequenceOfOperationEnum.HeatingWithReheat
      expression = expr1 and expr2
    }

    action(thermostat, ThermostatDevice) {
      // switch to Cool mode
      update(SimplifiedThermostat) {
        command(SimplifiedThermostat.setSystemMode(SimplifiedThermostatSystemModeEnum.Cool))
      }
    }
  }
}

Modificare la modalità di funzionamento della programmazione

La modalità di funzionamento della programmazione del termostato può essere modificata utilizzando Thermostat thermostatProgrammingOperationMode, i cui valori sono definiti da ProgrammingOperationModeBitmap.

API Device

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val thermostatTrait: Thermostat = thermostatTraitFlow.first()!!

if (thermostatTrait.supports(Thermostat.Attribute.thermostatProgrammingOperationMode)) {
  val programmingOperationMode = thermostatTrait.thermostatProgrammingOperationMode!!

  // Enable autoRecovery on the thermostatProgrammingOperationMode
  val unused =
    thermostatTrait.update {
      setThermostatProgrammingOperationMode(
        ThermostatTrait.ProgrammingOperationModeBitmap(
          programmingOperationMode.scheduleActive,
          true,
          programmingOperationMode.economy,
        )
      )
    }
}

API Automation

// When someone says "Reset programming operation mode"
val automation = automation {
  isActive = true
  sequential {
    val unused =
      starter<_>(structure, VoiceStarter.OkGoogleEvent) {
        parameter(VoiceStarter.OkGoogleEvent.query("Reset programming operation mode"))
      }
    // Set all the flags on the programming operation mode
    action(thermostat, ThermostatDevice) {
      update(Thermostat) {
        setThermostatProgrammingOperationMode(ProgrammingOperationModeBitmap(true, true, true))
      }
    }
  }
}

Modificare il setpoint della temperatura

Per modificare il setpoint della temperatura utilizzando Thermostat, chiama ThermostatTrait.SetpointRaiseLowerCommand.

API Device

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val thermostatTrait: Thermostat = thermostatTraitFlow.first()!!

// lower the temperature setpoint by 1 degree C.
// `amount` is in one tenth of a degree Celsius.
thermostatTrait.setpointRaiseLower(amount = -10, mode = SetpointRaiseLowerModeEnum.Cool)

API Automation

val automation = automation {
  isActive = true
  sequential {
    val stateReaderNode = stateReader<_>(thermostat, ThermostatDevice, Thermostat)
    // At 10:00pm
    val unused =
      starter<_>(structure, Time.ScheduledTimeEvent) {
        parameter(Time.ScheduledTimeEvent.clockTime(LocalTime.of(22, 0, 0, 0)))
      }
    // if the setpoint is warmer than 19C
    // `occupiedCoolingSetpoint` is in one hundredth of a degree C.
    condition() { expression = stateReaderNode.occupiedCoolingSetpoint greaterThan 1900 }

    // lower the temperature setpoint by 5 degrees C
    // Setpoint amount here is in one tenth of a degree Celsius.
    action(thermostat, ThermostatDevice) {
      command(Thermostat.setpointRaiseLower(SetpointRaiseLowerModeEnum.Cool, -50))
    }
  }
}

Dare la priorità a un setpoint della temperatura

Puoi dare la precedenza a un punto di controllo della temperatura rispetto a una programmazione preimpostata impostando l'attributo temperatureSetpointHold di ThermostatTrait su TemperatureSetpointHoldEnum.SetpointHoldOn oppure dare la precedenza alla programmazione impostandolo su TemperatureSetpointHoldEnum.SetpointHoldOff.

API Device

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val thermostatTrait: Thermostat = thermostatTraitFlow.first()!!

if (thermostatTrait.supports(Thermostat.Attribute.temperatureSetpointHold)) {
  // Set temperatureSetpointHold to SetpointHoldOn
  // allowing temperature setpoints to override any preprogrammed schedules.

  val unused =
    thermostatTrait.update {
      setTemperatureSetpointHold(TemperatureSetpointHoldEnum.SetpointHoldOn)
    }

API Automation

val automation = automation {
  isActive = true
  sequential {

    // When someone says "Prioritize thermostat setpoint"
    val unused =
      starter<_>(structure, VoiceStarter.OkGoogleEvent) {
        parameter(VoiceStarter.OkGoogleEvent.query("Prioritize thermostat setpoint"))
      }
    // make temperature setpoints override any preprogrammed schedules.
    action(thermostat, ThermostatDevice) {
      val unused2 =
        update(Thermostat) {
          setTemperatureSetpointHold(TemperatureSetpointHoldEnum.SetpointHoldOn)
        }
    }
  }

Imposta ThermostatTrait.Attributes.temperatureSetpointHoldDuration per controllare per quanti minuti è attivo un mantenimento del setpoint.

API Device

val thermostatTraitFlow: Flow<Thermostat?> =
  thermostat.type(ThermostatDevice).map { it.standardTraits.thermostat }.distinctUntilChanged()

val thermostatTrait: Thermostat = thermostatTraitFlow.first()!!

if (thermostatTrait.supports(Thermostat.Attribute.temperatureSetpointHoldDuration)) {
  // Set the setpoint hold duration to 60 minutes
  val unused = thermostatTrait.update { setTemperatureSetpointHoldDuration(60u) }
}

API Automation

val automation = automation {
  isActive = true
  sequential {
    val stateReaderNode = stateReader<_>(thermostat, ThermostatDevice, Thermostat)
    val unused = starter<_>(thermostat, ThermostatDevice, Thermostat)

    // if the temperature setpoint hold duration is less than 60 minutes...
    condition() { expression = stateReaderNode.temperatureSetpointHoldDuration.lessThan(60u) }

    // ...and the automation hasn't been run for at least 24 hours...
    suppressFor(Duration.ofHours(24))

    // ...set the temperature setpoint hold duration to 60 minutes
    action(thermostat, ThermostatDevice) {
      val unused2 = update(Thermostat) { setTemperatureSetpointHoldDuration(60u) }
    }
  }
}