Typ urządzenia dzwonek jest implementowany za pomocą 3 atrybutów:
PushAvStreamTransportTrait, który obsługuje transport strumienia audio i wideo za pomocą protokołów push,
WebRtcLiveViewTrait, który umożliwia sterowanie transmisjami na żywo i funkcją TalkBack, oraz
CameraSnapshotTrait, który zapewnia podgląd zrzutów ekranu z pamięci podręcznej i zrzuty ekranu na żywo.
Przed użyciem jakichkolwiek funkcji lub próbą aktualizacji atrybutów zawsze sprawdź, czy urządzenie obsługuje dany atrybut i polecenie. Więcej informacji znajdziesz w artykule Sterowanie urządzeniami naiOS.
| Typ urządzenia w interfejsach API Google Home | Cechy | Przykładowa aplikacja Swift | Przypadek użycia |
|---|---|---|---|
|
Dzwonek
Urządzenie uruchamiane przyciskiem na zewnątrz drzwi, które emituje sygnał dźwiękowy lub wizualny, służące do zwrócenia uwagi osoby znajdującej się po drugiej stronie drzwi. Dzwonki mogą oferować dostęp do transmisji na żywo, dwukierunkowej komunikacji lub wykrywania zdarzeń. |
Wymagane cechy google PushAvStreamTransportTrait google WebRtcLiveViewTrait |
Dzwonek |
Uzyskiwanie podstawowych informacji o urządzeniu
Zaimplementowano w przykładowej aplikacji na iOS
Atrybut BasicInformation zawiera informacje takie jak nazwa dostawcy, identyfikator dostawcy, identyfikator produktu, nazwa produktu (w tym informacje o modelu) i wersja oprogramowania urządzenia:
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!
Uzyskiwanie numeru seryjnego
Zaimplementowano w przykładowej aplikacji na iOS
Aby uzyskać numer seryjny urządzenia, użyj polecenia GetSerialNumber cechy ExtendedBasicInformation.
W przykładzie pokazano zapisywanie numeru seryjnego w zmiennej o nazwie serialNumber:
// Assuming extendedBasicInformationTrait: Google.ExtendedBasicInformationTrait let response = try await extendedBasicInformationTrait.getSerialNumber() let serialNumber = response.serialNumber
szybkie odpowiedzi.
Funkcja szybkich odpowiedzi umożliwia użytkownikowi wysłanie wstępnie zdefiniowanej wiadomości do dzwonka.
Ta funkcja jest dostępna tylko na dzwonkach. Lista wstępnie zdefiniowanych wiadomości jest dostępna dla aplikacji partnera, która może je wyświetlić użytkownikowi, aby mógł wybrać jedną z nich. Wiadomości wstępnie zdefiniowanych nie można edytować.
Szybkie odpowiedzi są implementowane za pomocą cechy PresetMessage.
Odtwarzanie gotowej wiadomości
Aby odtworzyć gotową wiadomość, wywołaj metodę playPresetMessage, przekazując jej jedną z wartości ciągu znaków we właściwości availablePhraseTypes.
import GoogleHomeSDK
import GoogleHomeTypes
func playDoorbellPresetMessage(device: HomeDevice, phraseTypeString: String) async {
// 1. Retrieve the GoogleDoorbellDeviceType helper on the device
guard let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) else {
print("This device is not a Google Doorbell or is currently uninitialized.")
return
}
// 2. Extract the Google.PresetMessageTrait
guard let presetMessageTrait = doorbellDeviceType.traits[Google.PresetMessageTrait.self] else {
print("PresetMessageTrait is not supported on this device.")
return
}
// 3. (Optional) Check available phrase types supported by the device
if let availablePhrases = presetMessageTrait.attributes.availablePhraseTypes {
let phraseTypeNames = availablePhrases.map { $0.phraseType }
print("Supported quick response phrases: \(phraseTypeNames)")
}
// 4. Send the playPresetMessage command asynchronously
do {
try await presetMessageTrait.playPresetMessage(phraseType: phraseTypeString)
print("Preset message successfully requested.")
} catch {
print("SDK error occurred playing preset message: \(error)")
}
}
Ustawianie języka wypowiedzi
Ustawianie języka wypowiedzi
Ustaw aktywny język mówiony urządzenia na określone ustawienia regionalne (np. „pl_PL”) za pomocą metody setActiveLocale cechy LocalizationConfiguration.
// Setting the active language // Assuming localizationConfigurationTrait: Matter.LocalizationConfigurationTrait let selectedLocale = "en_US" try await localizationConfigurationTrait.update { $0.setActiveLocale(selectedLocale) }
Pobieranie czasu ostatniego kontaktu urządzenia z chmurą
Aby znaleźć ostatni moment, w którym urządzenie miało kontakt z chmurą, użyj atrybutu lastContactTimestamp cechy ExtendedGeneralDiagnostics:
if let lastContactTimeStamp = extendedGeneralDiagnosticsTrait.attributes.lastContactTimestamp { self.lastContactTime = Date(timeIntervalSince1970: Double(lastConnectedTimeStamp)) }
Ustawienia typu mocowania kamery
Atrybut Mount zawiera ustawienia uchwytu kamery i informacje o jego stanie. Możesz odczytywać atrybuty, takie jak stan podłączenia, typ wykrywania i nazwa typu podłączenia.
Możesz też użyć cechy Mount, aby zastąpić domyślną konfigurację typu montażu.
// 1. Get the Mount trait guard let mountTrait = deviceType.traits[Google.MountTrait.self] else { print("Mount trait not supported or configured on this device.") return } // 2. Read the current mount state, detection type, and type name let mountState = mountTrait.attributes.mountState // Type: Google.MountTrait.MountStateEnum? let mountDetectionType = mountTrait.attributes.mountDetectionType // Type: Google.MountTrait.MountDetectionTypeEnum? let mountTypeName = mountTrait.attributes.mountTypeName // Type: String? // 3. Update the mount type override try await mountTrait.update { mutableTrait in mutableTrait.setMountTypeOverride(.official) }
Sprawdzanie połączenia urządzenia
Połączenie urządzenia jest sprawdzane na poziomie typu urządzenia, ponieważ niektóre urządzenia obsługują wiele typów urządzeń. Zwracany stan jest kombinacją stanów połączenia wszystkich cech na tym urządzeniu.
let doorbellConnectivity = doorbellDeviceType.metadata.sourceConnectivity.connectivityState
W przypadku różnych typów urządzeń, gdy nie ma połączenia z internetem, może być widoczny stan partiallyOnline. Niektóre standardowe cechy Matter mogą nadal być dostępne online dzięki lokalnemu routingowi, ale cechy działające w chmurze będą offline.
Uzyskiwanie adresu IP urządzenia
Aby znaleźć adres IP urządzenia, użyj atrybutu networkInterfaces zasobu GeneralDiagnosticsTrait.
Adresy są zwracane jako obiekty Data, które można sformatować jako standardowe ciągi IPv4 lub IPv6 za pomocą platformy Network:
func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
let interfaces = trait.attributes.networkInterfaces ?? []
var ipAddresses: [String] = []
for interface in interfaces {
for data in interface.iPv4Addresses {
if let ipv4 = IPv4Address(data) {
ipAddresses.append(String(describing: ipv4))
}
}
for data in interface.iPv6Addresses {
if let ipv6 = IPv6Address(data) {
ipAddresses.append(String(describing: ipv6))
}
}
}
return ipAddresses
}
Rozpoczynanie transmisji na żywo
Zaimplementowano w przykładowej aplikacji na iOS
Aby rozpocząć transmisję na żywo, wyślij ciąg protokołu opisu sesji (SDP) do metody startLiveView(offerSdp:) cechy WebRtcLiveViewTrait, która zwraca 3 wartości:
- SDP sesji.
- Czas trwania sesji w sekundach.
- Identyfikator sesji, który może służyć do przedłużenia lub zakończenia sesji.
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
}
}
Przedłużanie transmisji na żywo
Zaimplementowano w przykładowej aplikacji na iOS
Transmisje na żywo mają wstępnie ustawiony czas trwania, po którym wygasają. Aby wydłużyć czas trwania aktywnej transmisji, wyślij prośbę o rozszerzenie za pomocą metody 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
}
}
Włączanie i wyłączanie TalkBack
Zaimplementowano w przykładowej aplikacji na iOS
Aby rozpocząć rozmowę, wywołaj metodę startTalkback(mediaSessionId:optionalArgsProvider:) cechy WebRtcLiveViewTrait.
Aby zatrzymać, użyj 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)")
}
}
Zarządzanie transmisją na żywo
Zaimplementowano w przykładowej aplikacji na iOS
Dostosowanie jakości transmisji na żywo jest przydatne do optymalizacji wykorzystania przepustowości na podstawie kontekstu wyświetlania klienta (np. przełączenie na niższą rozdzielczość podczas wyświetlania mniejszego kafelka podglądu, widoku siatki lub trybu obrazu w obrazie).
Dynamiczna zmiana jakości za pomocą cechy WebRtcLiveView pozwala zarządzać rozdzielczością aktywnej sesji transmisji na żywo na konkretnym kliencie. Nie jest to to samo co skonfigurowanie ustawienia wykorzystania przepustowości na całym urządzeniu bezpośrednio na urządzeniu, co wpłynęłoby na wszystkich jednoczesnych widzów i jakość historycznych nagrań wideo zapisanych w chmurze.
Poniższy przykład pokazuje, jak pobrać i zaktualizować jakość transmisji na żywo na urządzeniu:
Pobieranie obsługiwanych opcji jakości: pobierz dostępne rozdzielczości strumieniowania obsługiwane przez urządzenie. Kod wysyła zapytanie do cechy
WebRtcLiveView, aby udostępnić obsługiwane jakości strumienia jako listę wartościQualityHint(takich jak.sd,.hd,.fhd,.qhdlub.uhd) za pomocą właściwościsupportedQualityHints.Zmień jakość transmisji na żywo: zastosuj wybraną wartość
QualityHint, aby zmienić rozdzielczość aktywnej transmisji na żywo (np. przełączyć ze standardowej rozdzielczości na wysoką rozdzielczość). FunkcjaupdateQualityHintużywa metodychangeLiveViewQualitycechyWebRtcLiveView, aby zastosować wybraną konfiguracjęQualityHintdo aktywnej sesji multimedialnej.
public var supportedQualityHints: [Google.WebRtcLiveViewTrait.QualityHint] { return liveViewTrait?.attributes.supportedQualityHints ?? [] } public func updateQualityHint( liveViewTrait: Google.WebRtcLiveViewTrait, hint: Google.WebRtcLiveViewTrait.QualityHint, mediaSessionId: String ) async { do { _ = try await liveViewTrait.changeLiveViewQuality( mediaSessionId: mediaSessionId, qualityHint: hint ) } catch { // error } }
Włączanie i wyłączanie funkcji nagrywania
Aby włączyć funkcję nagrywania, przekaż TransportStatusEnum.Active do metody setTransportStatus(transportStatus:optionalArgsProvider:) cechy PushAvStreamTransportTrait. Aby wyłączyć możliwość nagrywania, przekaż wartość TransportStatusEnum.Inactive.
W przykładzie poniżej opakowujemy te wywołania w jedno wywołanie, które używa Boolean do przełączania funkcji nagrywania:
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
}
}
}
Włączenie lub wyłączenie funkcji nagrywania przez kamerę jest równoznaczne z włączeniem lub wyłączeniem nagrywania przez nią filmów. Gdy nagrywanie przez kamerę jest włączone, kamera nagrywa (na potrzeby zdarzeń i powiązanych klipów).
Gdy funkcja nagrywania jest wyłączona (obraz z kamery jest wyłączony):
- Kamera może nadal wyświetlać się jako online zgodnie z
connectivityStatetypu urządzenia. - Nie można uzyskać dostępu do transmisji na żywo, a kamera nie wykrywa żadnych zdarzeń w chmurze.
Sprawdzanie, czy funkcja nagrywania jest włączona
Aby sprawdzić, czy funkcja nagrywania jest włączona, sprawdź, czy są aktywne jakieś połączenia. W poniższym przykładzie zdefiniowano 2 funkcje, które to robią:
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
}
Pobieranie zrzutów z kamery
Zaimplementowano w przykładowej aplikacji na iOS
Użyj cechy CameraSnapshot, aby pobierać statyczne migawki z kamery.
Te zrzuty są przydatne w kilku sytuacjach:
- jako kafelek zastępczy w interfejsie podczas wczytywania transmisji na żywo WebRTC.
- jako statyczny obraz podglądu, który po interakcji użytkownika zmienia się w transmisję na żywo;
- jako tło do rysowania i konfigurowania niestandardowych miejsc aktywności;
Cecha CameraSnapshot umożliwia pobieranie zdjęć na 2 sposoby, w zależności od tego, czy potrzebujesz zdjęcia z pamięci podręcznej do szybkiego renderowania, czy zdjęcia na żywo na żądanie.
Pobieranie podglądu z pamięci podręcznej
Zrzut podglądu to obraz z pamięci podręcznej, który pakiet SDK może pobrać bez wybudzania kamery. Jest to najszybsza metoda pobierania obrazu statycznego, która idealnie nadaje się do stron przeglądu kamer lub siatek panelu.
Aby uzyskać podgląd, odczytaj atrybut cechy preview_image_url:
guard let cameraSnapshotTrait = deviceType.traits[ Google.CameraSnapshotTrait.self ] else { print("CameraSnapshot trait not supported on this device.") return } if let previewImageUrlString = cameraSnapshotTrait .attributes.preview_image_url, let url = URL(string: previewImageUrlString) { // Load the preview image from the URL }
W zależności od konfiguracji i aktywności kamery adres URL podglądu wskazuje obraz z pamięci podręcznej wygenerowany na podstawie ostatniego nagrania wideo (pierwsza klatka kluczowa ostatniego fragmentu filmu) lub zrzut okresowo przesyłany przez kamerę.
Aby wskazać aktualność obrazu, chmura Google Home umieszcza w serwowanym obrazie JPEG/PNG nagłówek X-Home-Image-Captured-At w formacie UTC. Możesz przeanalizować ten nagłówek po stronie klienta, aby wyświetlić wiek migawki w aplikacji.
Pobieranie zrzutu na żywo na żądanie
W przypadku ścieżek użytkownika, które wymagają bieżącego podglądu na żywo z kamery (np. konfigurowania miejsc aktywności), możesz poprosić o migawkę na żywo. Uruchomienie podglądu na żywo powoduje wybudzenie kamery, przechwycenie nowej klatki i przesłanie jej do chmury.
Aby poprosić o zrzut na żywo, użyj polecenia getLiveSnapshot():
do { let response = try await cameraSnapshotTrait.getLiveSnapshot() let snapshotUrlString = response.snapshot_url if let url = URL(string: snapshotUrlString) { // Load the live snapshot image from the URL } } catch { print("Failed to get live snapshot: \(error)") }
Uwierzytelnianie żądań zrzutów
Zaimplementowano w przykładowej aplikacji na iOS
Wszystkie adresy URL zdjęć wskazują bezpieczne multimedia i wymagają tokena OAuth 2.0 dla zakresu interfejsów Home API w wersji 2. Aby pobrać i wyrenderować obrazy, token OAuth musi zostać wstawiony jako token okaziciela w nagłówku Authorization żądania HTTP.
Poniższy przykład pokazuje, jak skonfigurować bezpieczne żądanie sieciowe, aby pobrać zrzut:
import UIKit func loadSnapshotImage(from url: URL, home: Home) async -> UIImage? { do { // 1. Retrieve the OAuth access token from the Home APIs SDK let (accessToken, _) = try await home.permissions.authorization() // 2. Configure the HTTP GET request with the Bearer token var request = URLRequest(url: url) request.setValue( "Bearer \(accessToken)", forHTTPHeaderField: "Authorization" ) // 3. Fetch the image data let (data, _) = try await URLSession.shared.data(for: request) return UIImage(data: data) } catch { print("Error loading snapshot image: \(error)") return nil } }
Ustawienia baterii
Za pomocą interfejsów Home API można sterować różnymi ustawieniami baterii.
Ustawianie preferencji dotyczących wykorzystania baterii
Ustawienie balansu energii pozwala skonfigurować kompromis między czasem pracy na baterii a wydajnością urządzenia. Możesz utworzyć różne profile baterii, takie jak „Wydłużony”, „Zrównoważony” i „Wydajność”, i przełączać się między nimi.
Tę funkcję implementuje się przez zaktualizowanie atrybutu currentEnergyBalance cechy EnergyPreference. Atrybut akceptuje indeks liczby całkowitej, który odpowiada konkretnemu profilowi zdefiniowanemu na liście energyBalances urządzenia (np. 0 dla EXTENDED, 1 dla BALANCED i 2 dla PERFORMANCE).
Wartość null dla currentEnergyBalance oznacza, że urządzenie używa profilu niestandardowego. To jest stan tylko do odczytu.
Poniżej znajdziesz przykład struktury, której będzie używać atrybut currentEnergyBalance, a następnie rzeczywisty fragment kodu, który używa tego atrybutu.
// 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) } }
Włączanie automatycznego oszczędzania baterii
Zaimplementowano w przykładowej aplikacji na iOS
Aby skonfigurować tę funkcję, zaktualizuj atrybut currentLowPowerModeSensitivity cechy EnergyPreference. Ten atrybut używa indeksu do wyboru poziomu czułości, gdzie 0 zwykle reprezentuje Disabled, a 1 reprezentuje Enabled lub Automatic.
private func setAutoBatterySaver(to value: Bool) async throws { _ = try await energyPreferenceTrait.update { $0.setCurrentLowPowerModeSensitivity(value ? 1 : 0) } }
Sprawdzanie stanu ładowania baterii
Zaimplementowano w przykładowej aplikacji na iOS
Aby sprawdzić bieżący stan ładowania urządzenia (ładowanie, pełne naładowanie lub brak ładowania), użyj atrybutu batChargeState cechy 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" }
Sprawdzanie poziomu baterii
Aby sprawdzić bieżący poziom baterii, użyj atrybutu batChargeLevel cechy PowerSource. Poziom może być OK, Warning (niski) lub 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" }
Pobieranie źródła zasilania
Aby określić źródło zasilania, którego używa urządzenie, użyj atrybutów BatPresent i wiredPresent cechy PowerSource.
if powerSourceTrait.attributes.wiredPresent ?? false { self.powerSourceType = .wired } else if powerSourceTrait.attributes.batPresent ?? false { self.powerSourceType = .battery } else { self.powerSourceType = nil }
Sprawdzanie, czy bateria wymaga wymiany
Atrybut batReplaceability wskazuje, czy bateria jest niewymienna, wymienna przez użytkownika czy wymienna przez producenta.
Jeśli bateria jest wymienna, atrybut batReplacementNeeded cechy PowerSource informuje, czy należy ją wymienić.
// Get the battery replacement status var batteryStatus = powerSourceTrait.attributes.batReplacementNeeded if batteryStatus { print("Replace the battery.") }
Jeśli bateria może być wymieniana przez użytkownika, batReplacementDescription opisuje ją, podając informacje takie jak format, skład chemiczny i preferowany producent.
Ustawienia dźwięku
Za pomocą interfejsów Home API można sterować różnymi ustawieniami dźwięku.
Włączanie i wyłączanie mikrofonu
Aby włączyć lub wyłączyć mikrofon urządzenia, zaktualizuj atrybut microphoneMuted cechy CameraAvStreamManagementTrait, używając wbudowanej funkcji setMicrophoneMuted:
// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
do {
_ = try await self.cameraAvStreamManagementTrait?.update {
$0.setMicrophoneMuted(!on)
}
} catch {
// Error
}
}
Włączanie i wyłączanie nagrywania dźwięku
Aby włączyć lub wyłączyć nagrywanie dźwięku na urządzeniu, zaktualizuj atrybut recordingMicrophoneMuted cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcji setRecordingMicrophoneMuted:
// 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
}
}
Regulowanie głośności głośnika
Aby dostosować głośność głośnika urządzenia, zaktualizuj atrybut speakerVolumeLevel cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcji setSpeakerVolumeLevel:
// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setSpeakerVolumeLevel(value)
}
} catch {
// Error
}
}
Ustawienia strefy aktywności
Zaimplementowano w przykładowej aplikacji na iOS
Atrybut ZoneManagement udostępnia interfejs do zarządzania niestandardowymi obszarami zainteresowania (miejscami aktywności) na kamerach i dzwonkach.
Te strefy służą do filtrowania wykrywania zdarzeń (takich jak ruch osoby lub pojazdu) w określonych obszarach w polu widzenia urządzenia.
Miejsca aktywności są konfigurowane przez użytkownika w aplikacji partnera, co pozwala mu na rysowanie stref nad określonymi obszarami w polu widzenia kamery. Te zdefiniowane przez użytkownika strefy są następnie przekształcane w struktury używane przez tę cechę. Więcej informacji o tym, jak działają miejsca aktywności, znajdziesz w artykule Konfigurowanie i używanie miejsc aktywności.
Miejsca aktywności są zwykle definiowane za pomocą współrzędnych kartezjańskich 2D.
Atrybut udostępnia TwoDCartesianVertexStruct dla wierzchołków i TwoDCartesianZoneStruct dla definicji strefy (nazwa, wierzchołki, kolor i użycie).
Sprawdzanie miejsc aktywności
Aby wyświetlić miejsca aktywności, sprawdź atrybut zones cechy ZoneManagement.
let zoneManagementTrait: Google.ZoneManagementTrait self.zones = zoneManagementTrait.attributes.zones ?? []
Dodawanie strefy aktywności
Aby utworzyć nową strefę, użyj polecenia createTwoDCartesianZone. To polecenie przyjmuje parametr TwoDCartesianZoneStruct, który określa nazwę, wierzchołki, kolor i zastosowanie strefy.
Poniższy przykład pokazuje, jak utworzyć strefę o nazwie „Ganek” z 4 wierzchołkami, w kolorze łososiowym (#F439A0), która będzie używana do wykrywania ruchu.
import GoogleHomeSDK import GoogleHomeTypes func createFrontPorchZone(trait: Google.ZoneManagementTrait) async { // 1. Define the vertices for the zone (2D Cartesian coordinates) // Values are UInt16, typically scaled to the device's twoDCartesianMax. let vertices = [ Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 260, y = 422), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1049, y = 0), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 0), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 950), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1630, y = 1349), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 880, y = 2048), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 0, y = 2048), Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 638, y = 1090) ] // 2. Define the zone structure using the given SDK struct let newZone = Google.ZoneManagementTrait.TwoDCartesianZoneStruct( name: "Front Porch", use: [.motion], // ZoneUseEnum.motion vertices: vertices, // Color is a hex string (for example, Salmon/Pink) color: "#F439A0" ) do { // 3. Execute the raw command to add the zone to the device // This returns the created zone's ID (UInt16). var newZoneID = try await trait.createTwoDCartesianZone(zone: newZone) } catch { // Error } }
Aktualizowanie strefy aktywności
Aby zaktualizować istniejącą strefę, użyj polecenia updateTwoDCartesianZone. To polecenie wymaga zoneId i zaktualizowanego TwoDCartesianZoneStruct.
let zoneManagementTrait: Google.ZoneManagementTrait let zoneID: UInt16 let zone: Google.ZoneManagementTrait.TwoDCartesianZoneStruct do { _ = try await zoneManagementTrait.updateTwoDCartesianZone( zoneID: zoneID, zone: zone) } catch { // Error }
Usuwanie miejsc aktywności
Aby usunąć strefę, użyj polecenia removeZone z określonym zoneId.
let zoneManagementTrait: Google.ZoneManagementTrait let zoneID: UInt16 do { _ = try await zoneManagementTrait.removeZone(zoneID: zoneID) } catch { // Error }
Aktywatory wykrycia dźwięku
Cecha AvStreamAnalysis udostępnia interfejs do zarządzania aktywatorami wykrywania zdarzeń na kamerach i wideodomofonach. Wyzwalacze oparte na obrazie (np. osoby lub pojazdy) mogą być przypisane do konkretnej strefy, natomiast wyzwalacze związane z dźwiękiem są zwykle konfigurowane na poziomie urządzenia.
W przypadku wykrywania dźwięku za pomocą EventTriggerTypeEnum dostępne są te typy aktywatorów:
| Tryb | Wartość typu wyliczeniowego | Opis |
|---|---|---|
| Dźwięk | Sound |
Ogólne wykrywanie dźwięku. |
| Ktoś coś mówi | PersonTalking |
Wykrywa mowę. |
| szczekanie psa, | DogBark |
Wykrywa odgłosy psów. |
| Odgłos tłuczonego szkła | GlassBreak |
Wykrywa odgłos tłuczonego szkła. |
| Alarm z czujnika dymu | SmokeAlarm |
Wykrywa alarmy z czujnika dymu, często rozpoznawane po wzorcu dźwiękowym T3 (3 krótkie sygnały dźwiękowe, po których następuje przerwa). |
| alarm z czujnika tlenku węgla | CoAlarm |
Wykrywa alarmy tlenku węgla (CO), zwykle rozpoznawane po wzorcu dźwiękowym T4 (4 krótkie sygnały dźwiękowe, po których następuje przerwa). |
Sprawdzanie stanu wykrywania dźwięku
Aby wyświetlić użytkownikowi bieżący stan wykrywania dźwięku, musisz sprawdzić, co obsługuje urządzenie i co jest włączone przez sprzęt urządzenia. Te 2 atrybuty to:
W przypadku programowania na iOS zwykle uzyskuje się dostęp do cechy AvStreamAnalysis z urządzenia, aby odczytać te atrybuty.
// Example struct to store event triggers public struct EventTrigger: Equatable { public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum public var enabled: Bool } let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait let possibleEventTriggers = avStreamAnalysisTrait.attributes.supportedEventTriggers ?? [] let enabledEventTriggers = avStreamAnalysisTrait.attributes.enabledEventTriggers ?? [] let eventTriggers [EventTrigger] = [] for trigger in possibleEventTriggers { self.eventTriggers.append( EventTrigger( id: trigger, enabled: enabledEventTriggers.contains(trigger) ) ) }
Zaktualizuj zestaw włączonych reguł.
Aby zaktualizować zestaw włączonych aktywatorów, użyj polecenia SetOrUpdateEventDetectionTriggers, które przyjmuje listę struktur EventTriggerEnablement.
// Example struct to store event triggers public struct EventTrigger: Equatable { public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum public var enabled: Bool } let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait let eventTriggers: [EventTrigger] let enabledEventTriggers = eventTriggers.map { Google.AvStreamAnalysisTrait.EventTriggerEnablement( eventTriggerType: $0.id, enablementStatus: $0.enabled ? .enabled : .disabled ) } try await avStreamAnalysisTrait.setOrUpdateEventDetectionTriggers( eventTriggerEnablements: enabledEventTriggers )
Tryby nagrywania
Zaimplementowano w przykładowej aplikacji na iOS
Atrybut RecordingMode udostępnia interfejs do zarządzania nagrywaniem filmów i robieniem zdjęć na kamerach i dzwonkach. Umożliwia użytkownikom wybór między nagrywaniem ciągłym, nagrywaniem zdarzeń lub całkowitym wyłączeniem nagrywania (tylko podgląd na żywo).
RecordingModeEnum definiuje dostępne strategie nagrywania:
| Tryb | Wartość typu wyliczeniowego | Opis |
|---|---|---|
| Wyłączono | Disabled |
Nagrywanie jest całkowicie wyłączone. Używany głównie przez starsze urządzenia. |
| CVR (nagrywanie ciągłe) | Cvr |
Filmy są nagrywane przez całą dobę. Wymaga subskrypcji (np. Google Home Premium. |
| Nagrywanie zdarzeń | Ebr |
Nagrywanie jest aktywowane przez zdarzenia (osoba, ruch). Długość wideo zależy od czasu trwania zdarzenia i subskrypcji. |
| ETR (Event Triggered Recording) | Etr |
Krótkie nagranie podglądu (np. 10 sekund) wywoływane przez zdarzenia. |
| Live View | LiveView |
Nagrywanie jest wyłączone, ale użytkownicy nadal mogą uzyskać dostęp do transmisji na żywo. |
| Grafika | Images |
W przypadku wystąpienia zdarzeń zamiast filmów są rejestrowane zdjęcia. |
Sprawdzanie trybów nagrywania
Aby wyświetlić bieżącą konfigurację nagrywania, sprawdź atrybuty cechy RecordingMode:
supportedRecordingModes– wszystkie potencjalne trybyavailableRecordingModes– tryby do wyboruselectedRecordingMode– tryb aktywny
// Example struct to store recording modes. public struct RecordingMode: Hashable { public let id: UInt8 public let mode: Google.RecordingModeTrait.RecordingModeEnum } let recordingModeTrait: Google.RecordingModeTrait if let availableRecordingModes = recordingModeTrait.attributes.availableRecordingModes, let supportedRecordingModes = recordingModeTrait.attributes.supportedRecordingModes, let selectedRecordingMode = recordingModeTrait.attributes.selectedRecordingMode { var recordingModes: [RecordingMode] = [] for recordingModeId in availableRecordingModes { guard Int(recordingModeId) < supportedRecordingModes.count, Int(recordingModeId) >= 0 else { // Out of bounds error } recordingModes.append( RecordingMode( id: recordingModeId, mode: supportedRecordingModes[Int(recordingModeId)].recordingMode, ) ) } }
Zmiana trybu nagrywania
Przed aktualizacją upewnij się, że indeks wybrany z atrybutu supportedRecordingModes jest obecny w atrybucie availableRecordingModes.
Aby zaktualizować wybrany tryb, użyj funkcji setSelectedRecordingMode, przekazując indeks wybranego trybu:
let recordingModeTrait: Google.RecordingModeTrait let recordingModeID: UInt8 _ = try await recordingModeTrait.update { $0.setSelectedRecordingMode(recordingModeID) }
Inne ustawienia
Za pomocą interfejsów Home API można kontrolować różne inne ustawienia.
Włączanie i wyłączanie trybu nocnego
Aby włączyć lub wyłączyć tryb nocny kamery, użyj TriStateAutoEnum, aby zaktualizować atrybut nightVision cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcji setNightVision:
// Turn night vision on or off
func setNightVision(
to value: Google.CameraAvStreamManagementTrait.TriStateAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setNightVision(value)
}
} catch {
// Error
}
}
Zmienianie jasności diody LED stanu
Aby zmienić jasność diody LED stanu, użyj ThreeLevelAutoEnum, aby zaktualizować atrybut statusLightBrightness cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcji setStatusLightBrightness:
// Set the LED brightness
func setStatusLightBrightness(
to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setStatusLightBrightness(value)
}
} catch {
// Error
}
}
Zmiana widoku z kamery
Okno kamery jest takie samo jak w przypadku funkcji powiększania i przycinania opisanej w artykule pomocy Powiększanie i ulepszanie nagrań z kamery Nest.
Okno jest zdefiniowane w elemencie ViewportStruct, który zawiera 4 wartości używane jako współrzędne okna. Współrzędne są zdefiniowane w ten sposób:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
Określenie wartości ViewportStruct zależy od interfejsu aplikacji i implementacji aparatu. Aby ustawić obszar wyświetlania obrazu z kamery, zaktualizuj atrybut viewport cechy CameraAvStreamManagementTrait za pomocą ViewportStruct, używając wbudowanej funkcji setViewport.
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
}
}
}
Wygeneruj TransportOptionsStruct
Niektóre ustawienia wymagają modyfikacji właściwości w obiekcie TransportOptionsStruct, który jest następnie przekazywany do opcji transportu połączenia strumieniowego. W przypadku Swift tę strukturę należy wygenerować przed zaktualizowaniem właściwości.
Użyj tej funkcji pomocniczej, aby wygenerować strukturę do użycia z tymi zmianami ustawień:
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
}
Włączanie i wyłączanie statystyk
Każde urządzenie może indywidualnie wyrazić zgodę na wysyłanie szczegółowych danych analitycznych do chmury Google Home (patrz Cloud Monitoring dla interfejsów API Home).
Aby włączyć statystyki na urządzeniu, ustaw właściwość analyticsEnabled) obiektu ExtendedGeneralDiagnosticsTrait na true. Gdy ustawisz analyticsEnabled, inna właściwość, logUploadEnabled, zostanie automatycznie ustawiona na true, co umożliwi przesyłanie plików dziennika statystyk do chmury Google Home.
// Enable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
$0.setAnalyticsEnabled(true)
}
// Disable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
$0.setAnalyticsEnabled(false)
}
Konfiguracje transportu i nagrywania
Ta sekcja zawiera ustawienia związane z jakością strumienia z kamery i wyzwalaniem zdarzeń. Tymi ustawieniami zarządza cecha PushAvStreamTransport.
Odczytywanie ustawień transportu
W tej sekcji dowiesz się, jak pobrać bieżącą konfigurację z kamery lub dzwonka. Pobiera cechę PushAvStreamTransport, znajduje konkretne połączenie używane do nagrywania, a następnie wyodrębnia bieżące wartości jakości przepustowości, czułości wybudzania i maksymalnej długości zdarzenia.
// Assuming access to // var pushAvStreamTransportTrait: Google.PushAvStreamTransportTrait let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations // Locate the connection designated for recording let recordingConnection = connections.first { connection in guard let transportOptions = connection.transportOptions else { return false } return transportOptions.streamUsage == .recording } let options = recordingConnection?.transportOptions // 1. Bandwidth Quality (Video Stream ID) let videoStreamId = options?.videoStreamID // 2. Wake-up Sensitivity (Motion Sensitivity) let wakeUpSensitivity = options?.triggerOptions.motionSensitivity // 3. Max Event Length (Motion Trigger Time Control) let maxEventLength = options?.triggerOptions.motionTimeControl?.maxDuration
Aktualizowanie ustawień transportu
W tej sekcji dowiesz się, jak zmienić ustawienia transportu.
Tworzy nowy obiekt TransportOptionsStruct zawierający nowe wartości, a następnie używa polecenia modifyPushTransport, aby odesłać te zaktualizowane ustawienia do urządzenia i zastosować je do połączenia nagrywania znalezionego w poprzednim kroku.
Aby zmodyfikować te ustawienia, użyj polecenia modifyPushTransport z TransportOptionsStruct.
// Example: Updating to Max Quality and 30s duration let currentOptions = recordingConnection!.transportOptions! let newOptions = Google.PushAvStreamTransportTrait.TransportOptionsStruct( streamUsage: .recording, videoStreamID: 2, // Max Quality tlsEndpointID: currentOptions.tlsEndpointID, url: currentOptions.url, triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct( triggerType: .motion, motionSensitivity: 5, // Medium motionTimeControl: Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct( initialDuration: currentOptions.triggerOptions.motionTimeControl?.initialDuration ?? 10, augmentationDuration: currentOptions.triggerOptions.motionTimeControl?.augmentationDuration ?? 5, maxDuration: 30, blindDuration: currentOptions.triggerOptions.motionTimeControl?.blindDuration ?? 0 ) ), ingestMethod: currentOptions.ingestMethod, containerOptions: currentOptions.containerOptions ) try await pushAvStreamTransportTrait.modifyPushTransport( connectionID: recordingConnection!.connectionID, transportOptions: newOptions )
Określanie jakości przepustowości
Właściwość videoStreamId obiektu TransportOptionsStruct odpowiada konkretnej konfiguracji strumienia wideo.
Aby uzyskać obsługiwane strumienie wideo, zapoznaj się z atrybutem allocatedVideoStreams, który jest listą VideoStreamStructs.
z cechy CameraAvStreamManagement urządzenia.
Dostosowywanie czułości wybudzania urządzenia
Właściwość motionSensitivity obiektu TransportTriggerOptionsStruct odpowiada tym wartościom:
| Etykieta | Wartość (UInt8) |
|---|---|
| Niski | 1 |
| Średni | 5 |
| Wysoka | 10 |
Dostosowywanie maksymalnej długości wydarzenia
Właściwość maxDuration elementu TransportMotionTriggerTimeControlStruct odpowiada tym czasom trwania UInt32 (w sekundach):
- 10, 15, 30, 60, 120, 180
Ustawienia dzwonka
Za pomocą interfejsów Home API można sterować różnymi ustawieniami dzwonka.
Zmiana dźwięku dzwonka
Aby zmienić dźwięk dzwonka, najpierw pobierz listę dźwięków dzwonka zainstalowanych na urządzeniu, używając atrybutu installedChimeSounds cechy ChimeTrait:
doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
return chimeSound.chimeID, chimeSound.name
}
Następnie zaktualizuj atrybut selectedChime cechy ChimeTrait za pomocą wbudowanej funkcji setSelectedChime:
func setDoorbellChime(chimeID: UInt8) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setSelectedChime(chimeID)
}
} catch {
// Error
}
}
Używanie zewnętrznego dzwonka
Zaimplementowano w przykładowej aplikacji na iOS
Dzwonek można skonfigurować tak, aby używał zewnętrznego dzwonka, np. mechanicznego dzwonka zainstalowanego w domu. Należy to skonfigurować podczas instalacji dzwonka, aby uniknąć potencjalnego uszkodzenia dzwonka zewnętrznego.
Aby wskazać, jaki typ dzwonka zewnętrznego jest zainstalowany, użyj ExternalChimeType, aby zaktualizować atrybut externalChime cechy ChimeTrait za pomocą wbudowanej funkcji setExternalChime:
// Indicate the external chime is mechanical
func setExternalChime(to value: Google.ChimeTrait.ExternalChimeType) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setExternalChime(value)
}
} catch {
// Error
}
}
Zmienianie czasu trwania dzwonka zewnętrznego
Czas trwania dzwonka zewnętrznego w sekundach można skonfigurować za pomocą interfejsów Home API. Jeśli dzwonek zewnętrzny obsługuje czas trwania dzwonka, użytkownik może chcieć go skonfigurować.
Ustawiona tu wartość zależy od specyfikacji dzwonka zewnętrznego i zalecanego czasu trwania dzwonka.
Aby zmienić czas trwania dzwonka zewnętrznego, zaktualizuj atrybut externalChimeDurationSeconds cechy ChimeTrait, używając wbudowanej funkcji setExternalChimeDurationSeconds:
// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setExternalChimeDuration(value)
}
} catch {
// Error
}
}
Włączanie motywu dzwonka
Zaimplementowano w przykładowej aplikacji na iOS
Niektóre dzwonki mogą mieć dzwonki, które są dostępne dla użytkowników tylko przez ograniczony czas. Na przykład dzwonki związane ze świętami. Są to tzw. motywy dzwonka.
Aby sprawdzić, które motywy dzwonka są dostępne dla użytkownika, utwórz filtr przedziału czasu i użyj go do filtrowania wyników polecenia getAvailableThemes z cechy ChimeThemes. Spowoduje to wyświetlenie listy dostępnych motywów wraz z ich nazwami.
Poniższy przykład pokazuje, jak filtrować listę.
Motyw jest uznawany za aktywny, jeśli bieżący czas mieści się w jego godzinach rozpoczęcia i zakończenia (odpowiednio wartości startTimeSeconds i endTimeSeconds). Jeśli nie ustawisz czasu rozpoczęcia, będzie on uznawany za aktywny od początku czasu. Jeśli nie ustawisz godziny zakończenia, będzie ona aktywna przez cały czas. Jeśli brakuje obu tych elementów, motyw jest zawsze aktywny.
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)
}
}
}
Gdy poznasz nazwę motywu, którego chcesz użyć, np. Christmas, możesz go wybrać za pomocą funkcji setSelectedTimeboxedThemeName() w cesze ChimeThemes ChimeThemes.
private func setChimeTheme(to value: String) async throws {
_ = try await chimeThemeTrait.update {
$0.setSelectedTimeboxedThemeName(value)
}
}
Ustawienia komunikatów o gościach
Możesz sprawdzać ustawienia komunikatów o gościach dla dzwonków i nimi zarządzać za pomocą cechy VisitorAnnouncement interfejsów Home API. Ta cecha określa, czy obecność gościa jest ogłaszana na inteligentnych głośnikach lub wyświetlaczach Google, gdy ktoś dzwoni do drzwi.
Poniższy przykład pokazuje, jak sprawdzić, czy komunikaty o gościach są włączone, i jak zaktualizować to ustawienie:
let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled let value: Bool _ = try await self.visitorAnnouncementTrait?.update { $0.setVisitorAnnouncementsEnabled(value) }
Wycofywanie urządzenia
Aby usunąć dzwonek z domu, wywołaj funkcję device.decommission(). Wycofanie powoduje wyświetlenie użytkownikowi zarządzanego przez Google ekranu potwierdzenia z ostrzeżeniem, że cała historia całodobowych nagrań wideo, historia zdarzeń, klipy i dane z biblioteki znajomych twarzy zostaną trwale usunięte z całej struktury.
Szczegółowe instrukcje i przykłady kodu znajdziesz w artykule Usuwanie urządzenia.