Le type d'appareil "Sonnette" est implémenté à l'aide de deux traits :
PushAvStreamTransportTrait, qui gère le transport des flux audio et vidéo à l'aide de protocoles de type push, et
WebRtcLiveViewTrait, qui permet de contrôler les flux en direct et la fonctionnalité de communication bidirectionnelle.
Assurez-vous toujours qu'un appareil prend en charge les attributs et les commandes nécessaires avant d'utiliser une fonctionnalité ou de tenter de mettre à jour des attributs. Pour en savoir plus, consultez Contrôler les appareils suriOS.
| Type d'appareil des API Home | Traits | Application exemple Swift | Cas d'utilisation |
|---|---|---|---|
|
Sonnette
Appareil actionné par un bouton à l'extérieur d'une porte, qui émet un signal sonore et/ou visuel pour attirer l'attention d'une personne se trouvant de l'autre côté de la porte. Les sonnettes peuvent proposer un accès à des flux en direct, une fonctionnalité de communication bidirectionnelle ou générer des événements de détection. |
Traits requis google PushAvStreamTransportTrait google WebRtcLiveViewTrait |
Sonnette |
Obtenir des informations de base sur un appareil
Le trait BasicInformation inclut des informations telles que le nom du fournisseur, son ID, l'ID du produit, le nom du produit (y compris les informations sur le modèle), la version du logiciel et le numéro de série d'un appareil :
// [START get_device_information] let vendorName = basicInfoTrait.attributes.vendorName! let vendorID = basicInfoTrait.attributes.vendorID! let productID = basicInfoTrait.attributes.productID! let productName = basicInfoTrait.attributes.productName! let softwareVersion = basicInfoTrait.attributes.softwareVersion! let serialNumber = basicInfoTrait.attributes.serialNumber! // [END get_device_information]
Vérifier la connectivité d'un appareil
La connectivité d'un appareil est en fait vérifiée au niveau du type d'appareil, car certains appareils sont compatibles avec plusieurs types d'appareils. L'état renvoyé est une combinaison des états de connectivité de tous les traits de cet appareil.
let lightConnectivity = dimmableLightDeviceType.metadata.sourceConnectivity .connectivityState
L'état partiallyOnline peut être observé en cas de types d'appareils mixtes lorsqu'il n'y a pas de connexion Internet. Les traits standards Matter peuvent toujours être en ligne en raison du routage local, mais les traits basés sur le cloud seront hors connexion.
Lancer un flux en direct
Pour lancer un flux en direct, envoyez la chaîne SDP (Session Description Protocol) à la méthode startLiveView(offerSdp:) du trait WebRtcLiveViewTrait, qui renvoie trois valeurs :
- SDP de la session
- Durée de la session en secondes
- ID de la session, qui peut être utilisé pour la prolonger ou y mettre fin
public func sendOffer(offerSdp: String) async throws
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval)
{
do {
// Sending StartLiveView command
let response = try await liveViewTrait.startLiveView(
offerSdp: offerSdp
)
// Received StartLiveView response
return (
answerSdp: response.answerSdp,
mediaSessionId: response.mediaSessionId,
liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
)
} catch {
// Failed to send StartLiveView command
throw error
}
}
Prolonger un flux en direct
Les flux en direct ont une durée prédéfinie au terme de laquelle ils expirent. Pour prolonger la durée d'un flux actif, utilisez la méthode extendLiveView(mediaSessionId:optionalArgsProvider:) :
public func extendLiveView(mediaSessionId: String) async throws {
do {
// Extending live view
let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
} catch {
// Failed to extend live view
throw error
}
}
Démarrer et arrêter la conversation bidirectionnelle
Pour démarrer la conversation bidirectionnelle, appelez la méthode startTalkback(mediaSessionId:optionalArgsProvider:) du trait WebRtcLiveViewTrait.
Pour arrêter, utilisez stopTalkback(mediaSessionId:).
public func toggleTwoWayTalk(isOn: Bool, mediaSessionId: String) async throws {
do {
if isOn {
try await liveViewTrait.startTalkback(mediaSessionId: mediaSessionId)
} else {
try await liveViewTrait.stopTalkback(mediaSessionId: mediaSessionId)
}
} catch {
throw HomeError.commandFailed("Failed to toggle twoWayTalk: \(error)")
}
}
Activer et désactiver la capacité d'enregistrement
Pour activer la capacité d'enregistrement de la caméra, transmettez TransportStatusEnum.Active à la méthode setTransportStatus(transportStatus:optionalArgsProvider:) du trait PushAvStreamTransportTrait. Pour désactiver la capacité d'enregistrement, transmettez-lui TransportStatusEnum.Inactive.
Dans l'exemple suivant, nous encapsulons ces appels dans un seul appel qui utilise un Boolean pour activer ou désactiver la capacité d'enregistrement :
public func toggleIsRecording(isOn: Bool) {
self.uiState = .loading
guard let pushAvStreamTransportTrait else {
// PushAvStreamTransportTrait not found.
return
}
Task {
do {
try await pushAvStreamTransportTrait.setTransportStatus(
transportStatus: isOn ? .active : .inactive)
if isOn {
do {
self.player = try self.createWebRtcPlayer()
} catch {
// Failed to initialize WebRtcPlayer
self.uiState = .disconnected
return
}
await self.player?.initialize()
self.uiState = .live
} else {
self.player = nil
self.uiState = .off
}
} catch {
// Failed to toggle onOff
}
}
}
Activer ou désactiver la capacité d'enregistrement de la caméra revient à activer ou désactiver la vidéo de la caméra. Lorsqu'une caméra est activée, elle enregistre (pour les événements et les extraits associés).
Lorsque la capacité d'enregistrement est désactivée (la vidéo de la caméra est désactivée) :
- La caméra peut toujours apparaître comme étant en ligne, conformément à la
connectivityStatedu type d'appareil. - Le flux en direct n'est pas accessible et la caméra ne détecte aucun événement cloud.
Vérifier si la capacité d'enregistrement est activée
Pour savoir si la capacité d'enregistrement d'une caméra est activée, vérifiez si des connexions sont actives. L'exemple suivant définit deux fonctions pour ce faire :
public func isDeviceRecording() -> Bool {
guard let pushAvStreamTransportTrait else {
// PushAvStreamTransportTrait not found.
return false
}
guard
let hasActiveConnection =
pushAvStreamTransportTrait
.attributes
.currentConnections?
.contains(where: { $0.transportStatus == .active })
else {
return false
}
return hasActiveConnection
}
Paramètres de la batterie
Vous pouvez contrôler différents paramètres de batterie via les API Home.
Définir la préférence d'utilisation de la batterie
Le paramètre d'équilibre énergétique vous permet de configurer le compromis entre l'autonomie de la batterie et les performances d'un appareil. Vous pouvez créer différents profils de batterie (par exemple, "Autonomie prolongée", "Équilibré" et "Performances") et passer de l'un à l'autre.
Cette fonctionnalité est implémentée en mettant à jour l'attribut currentEnergyBalance du trait EnergyPreference. L'attribut accepte un index entier qui correspond à un profil spécifique défini dans la liste energyBalances de l'appareil (par exemple, 0 pour EXTENDED, 1 pour BALANCED et 2 pour PERFORMANCE).
Une valeur null pour currentEnergyBalance indique que l'appareil utilise un profil personnalisé. Il s'agit d'un état en lecture seule.
Vous trouverez ci-dessous un exemple de structure que l'attribut currentEnergyBalance utilisera, suivi de l'extrait de code réel qui utilise l'attribut.
// Example energyBalances list { "energy_balances": [ { "step": 0, "label": "EXTENDED" }, { "step": 50, "label": "BALANCED" }, { "step": 100, "label": "PERFORMANCE" } ] }
private func setBatteryUsage(to option: UInt8) async throws { _ = try await energyPreferenceTrait.update { $0.setCurrentEnergyBalance(option) } }
Activer l'économiseur de batterie automatique
Pour configurer cette fonctionnalité, mettez à jour l'attribut currentLowPowerModeSensitivity du trait EnergyPreference. Cet attribut utilise un index pour sélectionner un niveau de sensibilité, où 0 représente généralement Disabled et 1 représente Enabled ou Automatic.
private func setAutoBatterySaver(to value: Bool) async throws { _ = try await energyPreferenceTrait.update { $0.setCurrentLowPowerModeSensitivity(value ? 1 : 0) } }
Obtenir l'état de charge de la batterie
Pour obtenir l'état de charge actuel de l'appareil (en charge, complètement chargé ou non en charge), utilisez l'attribut batChargeState du trait PowerSource.
self.chargingState = powerSourceTrait.attributes.batChargeState var description: String switch self.chargingState { case .isCharging: description = "Charging" case .isAtFullCharge: description = "Full" case .isNotCharging: description = "Not Charging" default: description = "Unknown" }
Obtenir le niveau de batterie
Pour obtenir le niveau de batterie actuel, utilisez l'attribut batChargeLevel du trait PowerSource. Le niveau est OK, Warning (bas) ou Critical.
self.batteryLevel = powerSourceTrait.attributes.batChargeLevel var description: String switch self.batteryLevel { case .ok: description = "OK" case .warning: description = "Warning" case .critical: description = "Critical" default: description = "Unknown" }
Obtenir la source d'alimentation
Pour déterminer la source d'alimentation utilisée par l'appareil, utilisez les attributs BatPresent et wiredPresent du trait PowerSource.
if powerSourceTrait.attributes.wiredPresent ?? false { self.powerSourceType = .wired } else if powerSourceTrait.attributes.batPresent ?? false { self.powerSourceType = .battery } else { self.powerSourceType = nil }
Paramètres audio
Vous pouvez contrôler différents paramètres audio à l'aide des API Home.
Activer ou désactiver le micro
Pour activer ou désactiver le micro de l'appareil, mettez à jour l'attribut microphoneMuted du trait CameraAvStreamManagementTrait à l'aide de la fonction setMicrophoneMuted intégrée :
// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
do {
_ = try await self.cameraAvStreamManagementTrait?.update {
$0.setMicrophoneMuted(!on)
}
} catch {
// Error
}
}
Activer ou désactiver l'enregistrement audio
Pour activer ou désactiver l'enregistrement audio de l'appareil, mettez à jour l'attribut recordingMicrophoneMuted du trait CameraAvStreamManagementTrait à l'aide de la fonction setRecordingMicrophoneMuted intégrée :
// Turn audio recording on or off for the device
func setAudioRecording(on: Bool) async {
do {
_ = try await self.cameraAvStreamManagementTrait?.update {
$0.setRecordingMicrophoneMuted(!on)
}
} catch {
// Error
}
}
Régler le volume du haut-parleur
Pour ajuster le volume du haut-parleur de l'appareil, mettez à jour l'attribut speakerVolumeLevel du trait CameraAvStreamManagementTrait à l'aide de la fonction setSpeakerVolumeLevel intégrée :
// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setSpeakerVolumeLevel(value)
}
} catch {
// Error
}
}
Autres paramètres
Vous pouvez contrôler d'autres paramètres à l'aide des API Home.
Activer ou désactiver la vision nocturne
Pour activer ou désactiver la vision nocturne de la caméra, utilisez TriStateAutoEnum pour mettre à jour l'attribut nightVision du trait CameraAvStreamManagementTrait à l'aide de la fonction setNightVision intégrée :
// Turn night vision on or off
func setNightVision(
to value: Google.CameraAvStreamManagementTrait.TriStateAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setNightVision(value)
}
} catch {
// Error
}
}
Modifier la luminosité du voyant d'état
Pour modifier la luminosité du voyant d'état, utilisez ThreeLevelAutoEnum pour mettre à jour l'attribut statusLightBrightness du trait CameraAvStreamManagementTrait à l'aide de la fonction setStatusLightBrightness intégrée :
// Set the LED brightness
func setStatusLightBrightness(
to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setStatusLightBrightness(value)
}
} catch {
// Error
}
}
Modifier le champ de vision de la caméra
Le champ de vision de la caméra est identique à la fonctionnalité "Zoomer et recadrer" décrite dans l'article d'aide Zoomer et améliorer l'affichage vidéo de la caméra Nest.
Le champ de vision est défini dans un ViewportStruct qui contient quatre valeurs utilisées comme coordonnées du champ de vision. Les coordonnées sont définies comme suit :
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
La détermination des valeurs pour ViewportStruct dépend de l'UI et de l'implémentation de la caméra d'une application. Pour définir le champ de vision de la vidéo de la caméra, mettez à jour l'attribut viewport du trait CameraAvStreamManagementTrait avec un ViewportStruct à l'aide de la fonction setViewport intégrée.
func setCrop(x1: UInt16, y1: UInt16, x2: UInt16, y2: UInt16) {
let viewport = Google.CameraAvStreamManagementTrait.ViewportStruct(
x1: x1,
y1: y1,
x2: x2,
y2: y2
)
Task {
do {
try await cameraAvStreamManagementTrait.update {
$0.setViewport(viewport)
}
} catch {
// Error
}
}
}
Générer un TransportOptionsStruct
Certains paramètres nécessitent de modifier les propriétés d'un TransportOptionsStruct, qui est ensuite transmis aux options de transport d'une connexion de flux en continu. Pour Swift, cette structure doit être générée avant la mise à jour des propriétés.
Utilisez cette fonction d'assistance pour générer la structure à utiliser avec les modifications de paramètres suivantes :
func getTransportOptions(
transportOptions: Google.PushAvStreamTransportTrait.TransportOptionsStruct,
wakeUpSensitivity: UInt8?,
maxEventLength: UInt32?
) async throws
-> Google.PushAvStreamTransportTrait.TransportOptionsStruct
{
var newMotionTimeControl:
Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct? = nil
if let maxEventLength {
guard let motionTimeControl = transportOptions.triggerOptions.motionTimeControl else {
throw HomeError.failedPrecondition(
// Error - cannot update max event length without motion time control
}
newMotionTimeControl =
Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
initialDuration: motionTimeControl.initialDuration,
augmentationDuration: motionTimeControl.augmentationDuration,
maxDuration: maxEventLength,
blindDuration: motionTimeControl.blindDuration
)
}
return Google.PushAvStreamTransportTrait.TransportOptionsStruct(
streamUsage: .recording,
videoStreamID: nil,
audioStreamID: nil,
tlsEndpointID: transportOptions.tlsEndpointID,
url: transportOptions.url,
triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
triggerType: .motion,
motionZones: nil,
motionSensitivity: wakeUpSensitivity,
motionTimeControl: newMotionTimeControl,
maxPreRollLen: nil
),
ingestMethod: .cmafIngest,
containerOptions: Google.PushAvStreamTransportTrait.ContainerOptionsStruct(
containerType: .cmaf,
cmafContainerOptions: nil
),
expiryTime: nil
)
}
private func getRecordingConnection() async throws
-> Google.PushAvStreamTransportTrait.TransportConfigurationStruct?
{
guard let pushAvStreamTransportTrait else {
// Error - PushAvStreamTransport trait not available
return nil
}
let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations
for connection in connections {
guard let transportOptions = connection.transportOptions,
transportOptions.streamUsage == .recording
else {
continue
}
return connection
}
return nil
}
Ajuster la sensibilité d'activation de l'appareil
La sensibilité d'activation de l'appareil permet d'économiser la batterie en réduisant la plage à laquelle l'appareil peut détecter une activité et en augmentant le temps d'activation après la détection de cette activité.
Dans les API Home, cette propriété peut être définie à l'aide de la propriété motionSensitivity de triggerOptions dans les transportOptions de l'appareil. Ces options sont définies dans le trait PushAvStreamTransportTrait pour chaque appareil.
La sensibilité d'activation ne peut être définie que sur les valeurs suivantes :
- 1 = Faible
- 5 = Moyen
- 10 = Élevé
Pour mettre à jour la configuration, vous devez trouver la configuration de transport des flux d'enregistrement actifs à l'aide de la commande findTransport, puis modifier la configuration avec la nouvelle valeur de sensibilité à l'aide de la commande modifyPushTransport.
La commande modifyPushTransport nécessite de transmettre l'intégralité de TransportOptionsStruct. Vous devez donc d'abord copier les valeurs existantes de la configuration actuelle. Consultez Générer un TransportOptionsStruct pour obtenir une fonction d'assistance permettant d'effectuer cette opération.
func setWakeUpSensitivity(to value: UInt8) async {
do {
let connection = try await getRecordingConnection()
guard let connection,
let transportOptions = connection.transportOptions
else {
// Error - Transport options not available
return
}
guard transportOptions.triggerOptions.motionSensitivity != nil else {
// Error - Motion sensitivity not available to be updated for this device
return
}
try await pushAvStreamTransportTrait.modifyPushTransport(
connectionID: connection.connectionID,
transportOptions: self.getTransportOptions(
transportOptions: transportOptions,
wakeUpSensitivity: value,
maxEventLength: nil
)
)
} catch {
// Error
}
}
Ajuster la durée maximale des événements
La durée maximale des événements correspond à la durée d'enregistrement vidéo d'un événement par la caméra. Grâce aux API Home, vous pouvez configurer cette propriété pour chaque appareil, avec les mêmes durées que dans Google Home app (GHA), par intervalles de secondes :
- 10 secondes
- 15 secondes
- 30 secondes
- 60 secondes (1 minute)
- 120 secondes (2 minutes)
- 180 secondes (3 minutes)
Dans les API Home, cette propriété peut être définie à l'aide de la propriété motionTimeControl de triggerOptions dans les transportOptions de l'appareil. Ces options sont définies dans le trait PushAvStreamTransportTrait pour chaque appareil.
Pour mettre à jour la configuration, vous devez trouver la configuration de transport des flux d'enregistrement actifs à l'aide de la commande findTransport, puis modifier la configuration avec la nouvelle valeur de durée de l'événement à l'aide de la commande modifyPushTransport.
La commande modifyPushTransport nécessite de transmettre l'intégralité de TransportOptionsStruct. Vous devez donc d'abord copier les valeurs existantes de la configuration actuelle. Consultez Générer un TransportOptionsStruct pour obtenir une fonction d'assistance permettant d'effectuer cette opération.
func setMaxEventLength(to value: UInt32) async {
do {
let connection = try await getRecordingConnection()
guard let connection,
let transportOptions = connection.transportOptions
else {
// Error - Transport options not available
return
}
guard transportOptions.triggerOptions.motionTimeControl != nil else {
// Error - Motion time control not available to be updated for this device
return
}
try await pushAvStreamTransportTrait.modifyPushTransport(
connectionID: connection.connectionID,
transportOptions: self.getTransportOptions(
transportOptions: transportOptions,
wakeUpSensitivity: nil,
maxEventLength: value
)
)
} catch {
// Error
}
}
Paramètres du carillon
Vous pouvez contrôler différents paramètres du carillon de la sonnette via les API Home.
Modifier le son du carillon
Pour modifier le son de la sonnerie, commencez par obtenir la liste des sons de sonnerie installés sur l'appareil à l'aide de l'attribut installedChimeSounds du trait ChimeTrait :
doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
return chimeSound.chimeID, chimeSound.name
}
Ensuite, mettez à jour l'attribut selectedChime du trait ChimeTrait à l'aide de la fonction setSelectedChime intégrée :
func setDoorbellChime(chimeID: UInt8) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setSelectedChime(chimeID)
}
} catch {
// Error
}
}
Utiliser un carillon externe
La sonnette peut être configurée pour utiliser un carillon externe, comme une cloche mécanique installée à l'intérieur de la maison. Ce paramètre doit être configuré lors de l'installation de la sonnette pour éviter d'endommager le carillon externe.
Pour indiquer le type de carillon externe installé, utilisez ExternalChimeType pour mettre à jour l'attribut externalChime du trait ChimeTrait à l'aide de la fonction setExternalChime intégrée :
// Indicate the external chime is mechanical
func setExternalChime(to value: Google.ChimeTrait.ExternalChimeType) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setExternalChime(value)
}
} catch {
// Error
}
}
Modifier la durée du carillon externe
La durée, en secondes, pendant laquelle une sonnerie externe sonne peut être configurée à l'aide des API Home. Si le carillon externe prend en charge une durée de sonnerie, l'utilisateur peut souhaiter la configurer.
La valeur définie ici dépend des spécifications du carillon externe lui-même et de la durée recommandée du carillon.
Pour modifier la durée de la sonnerie externe, mettez à jour l'attribut externalChimeDurationSeconds du trait ChimeTrait à l'aide de la fonction setExternalChimeDurationSeconds intégrée :
// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setExternalChimeDuration(value)
}
} catch {
// Error
}
}
Activer un thème de carillon
Certaines sonnettes peuvent proposer des carillons qui ne sont disponibles que pour une durée limitée. Par exemple, des carillons spécifiques aux jours fériés. C'est ce qu'on appelle des thèmes de carillon.
Pour voir quels thèmes de carillon sont disponibles pour un utilisateur, créez un filtre de timebox et utilisez-le pour filtrer les résultats de la commande getAvailableThemes à partir du trait ChimeThemes. Cette commande renvoie une liste des thèmes disponibles, y compris leurs noms.
L'exemple suivant montre comment filtrer la liste.
Un thème est considéré comme actif si l'heure actuelle est comprise entre ses heures de début et de fin (les valeurs startTimeSeconds et endTimeSeconds, respectivement). Si aucune heure de début n'est définie, elle est considérée comme active depuis le début. Si aucune heure de fin n'est définie, elle reste active indéfiniment. Si les deux sont manquants, le thème est toujours actif.
let chimeThemes = try await chimeThemeTrait.getAvailableThemes().themes
if !chimeThemes.isEmpty {
var chimeThemeSettings = []
for chimeTheme in chimeThemes {
let currentDateTime = UInt64(Date().timeIntervalSince1970)
// Only show chime themes that are active.
if chimeTheme.startTimeSeconds ?? 0 <= currentDateTime
&& chimeTheme.endTimeSeconds ?? UInt64.max >= currentDateTime
{
self.chimeThemeSettings.append(chimeTheme.name)
}
}
}
Une fois que vous avez le nom du thème souhaité, tel que Christmas, vous pouvez le sélectionner à l'aide de la fonction setSelectedTimeboxedThemeName() sur le trait ChimeThemes ChimeThemes.
private func setChimeTheme(to value: String) async throws {
_ = try await chimeThemeTrait.update {
$0.setSelectedTimeboxedThemeName(value)
}
}```