Тип устройства "Дверной звонок" реализован с помощью трех функций:
PushAvStreamTransportTrait, которая обрабатывает передачу аудио- и видеопотоков с помощью протоколов на основе push-уведомлений;
WebRtcLiveViewTrait, которая позволяет управлять трансляциями и двусторонней связью; и
CameraSnapshotTrait, которая предоставляет кешированные снимки экрана и позволяет делать снимки экрана в реальном времени.
Перед использованием функций или попыткой обновить атрибуты всегда проверяйте, поддерживаются ли они устройством. Подробнее о том, как управлять устройствами на сайтеiOS…
| Тип устройства для Home API | Функции | Пример приложения на языке Swift | История успеха |
|---|---|---|---|
|
Дверной звонок
Устройство, которое активируется кнопкой снаружи двери и издает звуковой и/или визуальный сигнал, чтобы привлечь внимание человека, находящегося по другую сторону двери. Дверные звонки могут поддерживать доступные трансляции, двустороннюю связь и обнаружение событий. |
Обязательные характеристики google PushAvStreamTransportTrait google WebRtcLiveViewTrait |
Дверной звонок |
Как получить основную информацию об устройстве
Реализовано в примере приложения для iOS
BasicInformation
содержит такую информацию об устройстве, как название и идентификатор поставщика, идентификатор и название товара (включая информацию о модели), а также версию ПО:
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!
Получить серийный номер
Реализовано в примере приложения для iOS
Чтобы получить серийный номер устройства, используйте команду GetSerialNumber из черты ExtendedBasicInformation.
В примере показано, как сохранить серийный номер в переменной serialNumber:
// Assuming extendedBasicInformationTrait: Google.ExtendedBasicInformationTrait let response = try await extendedBasicInformationTrait.getSerialNumber() let serialNumber = response.serialNumber
быстрые ответы.
Функция быстрых ответов позволяет пользователю отправлять на дверной звонок заранее заданные сообщения.
Эта функция доступна только на устройствах дверного звонка. Список стандартных сообщений доступен в приложении партнера, который может предложить пользователю выбрать одно из них. Готовые сообщения нельзя редактировать.
Функция быстрых ответов реализована с помощью черты PresetMessage.
Как воспроизвести заранее записанное сообщение
Чтобы воспроизвести стандартное сообщение, вызовите метод playPresetMessage, передав ему одно из строковых значений, найденных в свойстве 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)")
}
}
Как выбрать язык озвучивания
Как выбрать язык озвучивания
Установить для устройства активный разговорный язык с определенной локалью (например, "en_US") с помощью метода setActiveLocale из признака LocalizationConfiguration.
// Setting the active language // Assuming localizationConfigurationTrait: Matter.LocalizationConfigurationTrait let selectedLocale = "en_US" try await localizationConfigurationTrait.update { $0.setActiveLocale(selectedLocale) }
Как узнать время последнего подключения устройства к облаку
Чтобы узнать, когда устройство в последний раз подключалось к облаку, используйте атрибут lastContactTimestamp из черты ExtendedGeneralDiagnostics:
if let lastContactTimeStamp = extendedGeneralDiagnosticsTrait.attributes.lastContactTimestamp { self.lastContactTime = Date(timeIntervalSince1970: Double(lastConnectedTimeStamp)) }
Настройки типа крепления камеры
Свойство Mount содержит настройки крепления камеры и информацию о ее статусе. Вы можете просматривать такие атрибуты, как статус подключения, тип обнаружения и название типа подключения.
Кроме того, вы можете использовать признак Mount, чтобы переопределить конфигурацию типа крепления по умолчанию.
// 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) }
Как проверить подключение устройства
На самом деле подключение устройства проверяется на уровне типа устройства, поскольку некоторые устройства поддерживают несколько типов. Возвращаемое состояние представляет собой сочетание состояний подключения для всех характеристик устройства.
let doorbellConnectivity = doorbellDeviceType.metadata.sourceConnectivity.connectivityState
Статус partiallyOnline может наблюдаться при использовании устройств разных типов, если нет подключения к интернету. Matter стандартные функции могут быть доступны онлайн благодаря локальной маршрутизации, но облачные функции будут недоступны.
Как узнать IP-адрес устройства
Чтобы найти IP-адрес устройства, используйте атрибут networkInterfaces элемента GeneralDiagnosticsTrait.
Адреса возвращаются в виде объектов Data, которые можно отформатировать в стандартные строки IPv4 или IPv6 с помощью фреймворка 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
}
Как начать трансляцию
Реализовано в примере приложения для iOS
Чтобы начать трансляцию, отправьте строку протокола описания сеанса (SDP) в метод startLiveView(offerSdp:)WebRtcLiveViewTrait, который возвращает три значения:
- SDP для сеанса.
- Длительность сеанса в секундах.
- Идентификатор сеанса, который можно использовать для его продления или завершения.
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
}
}
Как продлить трансляцию
Реализовано в примере приложения для iOS
У трансляций есть ограничение по длительности, по достижении которого они автоматически прекращаются. Чтобы увеличить продолжительность активного потока, отправьте запрос на продление с помощью метода 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
}
}
Как включить и отключить TalkBack
Реализовано в примере приложения для iOS
Чтобы начать разговор, вызовите метод startTalkback(mediaSessionId:optionalArgsProvider:) из WebRtcLiveViewTrait.
Чтобы остановить запись, нажмите 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)")
}
}
Как управлять трансляцией
Реализовано в примере приложения для iOS
Изменение качества трансляции позволяет оптимизировать использование пропускной способности сети в зависимости от контекста просмотра (например, переключаться на более низкое разрешение при показе небольшого фрагмента, сетки или в режиме "картинка в картинке").
Динамическое изменение качества с помощью функции
WebRtcLiveView
позволяет управлять разрешением активной сессии трансляции на определенном клиенте. Это не то же самое, что настроить использование пропускной способности на уровне устройства, поскольку в этом случае будут затронуты все пользователи, одновременно просматривающие видео, и качество видеозаписей, сохраненных в облаке.
В следующем примере показано, как получить и обновить качество трансляции для устройства:
Получение поддерживаемых вариантов качества. Узнайте, какие разрешения потоковой передачи поддерживает устройство. Код запрашивает черту
WebRtcLiveView, чтобы получить список поддерживаемых качеств потока в виде значенийQualityHint(например,.sd,.hd,.fhd,.qhdили.uhd) с помощью свойстваsupportedQualityHints.Изменить качество трансляции: применить выбранный
QualityHint, чтобы изменить разрешение активной трансляции (например, переключиться со стандартного разрешения на высокое). ФункцияupdateQualityHintиспользует методchangeLiveViewQualityпризнакаWebRtcLiveView, чтобы применить выбранную конфигурациюQualityHintк активному сеансу воспроизведения медиаконтента.
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 } }
Как включить и отключить возможность записи
Чтобы включить запись с камеры, передайте значение TransportStatusEnum.Active методу setTransportStatus(transportStatus:optionalArgsProvider:) признака PushAvStreamTransportTrait. Чтобы отключить возможность записи, передайте его
TransportStatusEnum.Inactive.
В приведенном ниже примере эти вызовы объединены в один, в котором используется Boolean для включения и отключения записи:
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
}
}
}
Включение и отключение записи видео камерой аналогично включению и отключению видео с камеры. Когда видео с камеры включено, она записывает видео (для событий и связанных с ними клипов).
Если запись отключена (видео с камеры отключено):
- Камера может по-прежнему отображаться как онлайн в соответствии с
connectivityStateтипа устройства. - Нет доступа к трансляции, а камера не обнаруживает облачных событий.
Проверьте, включена ли возможность записи
Чтобы узнать, включена ли запись с камеры, проверьте, есть ли активные подключения. В примере ниже определены две функции, которые выполняют эту задачу:
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
}
Получать снимки с камеры
Реализовано в примере приложения для iOS
Используйте функцию CameraSnapshot, чтобы получать статические снимки с камеры.
Снимки полезны в следующих случаях:
- В качестве заполнителя в интерфейсе, пока загружается трансляция WebRTC.
- В виде статического изображения, которое при взаимодействии с пользователем превращается в прямую трансляцию.
- В качестве фона для рисования и настройки специальных зон активности.
Свойство CameraSnapshot позволяет получать снимки двумя способами в зависимости от того, нужен ли вам кешированный снимок для быстрой отрисовки или снимок по запросу.
Как получить снимок из кеша
Предварительный снимок – это сохраненное в кеше изображение, которое SDK может получить, не включая камеру. Это самый быстрый способ получить статичное изображение, который идеально подходит для страниц обзора камеры или сеток на панели управления.
Чтобы получить снимок предпросмотра, прочитайте атрибут признака 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 }
В зависимости от конфигурации камеры и действий пользователя URL предпросмотра ведет на кешированное изображение, созданное на основе недавней видеозаписи (первый I-кадр последнего фрагмента видео), или на снимок, периодически загружаемый камерой.
Чтобы указать, когда было сделано изображение, облако Google Home встраивает заголовок X-Home-Image-Captured-At в полученное изображение JPEG/PNG, отформатированное в формате UTC. Вы можете выполнить синтаксический анализ этого заголовка на клиентской стороне, чтобы показывать возраст снимка в приложении.
Как получить снимок экрана в реальном времени
Если вам нужно посмотреть текущую трансляцию с камеры, например чтобы настроить зоны слежения, вы можете запросить снимок. При срабатывании функции создания снимка камера включается, делает новый кадр и загружает его в облако.
Чтобы запросить снимок в реальном времени, используйте команду 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)") }
Как аутентифицировать запросы снимков
Реализовано в примере приложения для iOS
Все URL снимков указывают на защищенные медиафайлы и требуют токен OAuth 2.0 для области действия Home APIs v2. Чтобы скачать и обработать изображения, токен OAuth необходимо внедрить в качестве токена на предъявителя в заголовок Authorization HTTP-запроса.
В примере ниже показано, как настроить безопасный сетевой запрос для скачивания снимка:
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 } }
Настройки батареи
Различные настройки батареи можно контролировать с помощью API Home.
Как задать настройки расхода заряда батареи
Настройка баланса энергопотребления позволяет выбрать оптимальное соотношение между временем работы от батареи и производительностью устройства. Вы можете создать несколько профилей батареи, например "Экономия заряда", "Сбалансированный" и "Производительность", и переключаться между ними.
Эта функция реализована путем обновления атрибута currentEnergyBalance в чертеже EnergyPreference. Атрибут принимает целочисленный индекс, соответствующий определенному профилю в списке energyBalances устройства (например, 0 для EXTENDED, 1 для BALANCED и 2 для PERFORMANCE).
Значение null для параметра currentEnergyBalance указывает, что на устройстве используется специальный профиль. Это состояние доступно только для чтения.
Ниже приведен пример структуры, которую использует атрибут "цена со скидкой" currentEnergyBalance, а затем фрагмент кода, в котором используется этот атрибут.
// 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) } }
Как включить автоматический режим энергосбережения
Реализовано в примере приложения для iOS
Чтобы настроить эту функцию, обновите атрибут currentLowPowerModeSensitivity в чертеже EnergyPreference. В этом атрибуте для выбора уровня конфиденциальности используется индекс, где 0 обычно соответствует Disabled, а 1 – Enabled или Automatic.
private func setAutoBatterySaver(to value: Bool) async throws { _ = try await energyPreferenceTrait.update { $0.setCurrentLowPowerModeSensitivity(value ? 1 : 0) } }
Как узнать состояние зарядки батареи
Реализовано в примере приложения для iOS
Чтобы узнать текущее состояние зарядки устройства (заряжается, полностью заряжено или не заряжается), используйте атрибут batChargeState из трейта 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" }
Как узнать уровень заряда батареи
Чтобы получить текущий уровень заряда батареи, используйте атрибут batChargeLevel из черты PowerSource. Уровень может быть OK, Warning (низкий) или 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" }
Как узнать источник питания
Чтобы определить, какой источник питания использует устройство, воспользуйтесь атрибутами BatPresent и wiredPresent признака PowerSource.
if powerSourceTrait.attributes.wiredPresent ?? false { self.powerSourceType = .wired } else if powerSourceTrait.attributes.batPresent ?? false { self.powerSourceType = .battery } else { self.powerSourceType = nil }
Проверьте, нужно ли заменить батарею.
Атрибут batReplaceability указывает, можно ли заменить батарею самостоятельно или это можно сделать только на заводе.
Если батарею можно заменить, атрибут batReplacementNeeded в чертеже PowerSource указывает, нужно ли ее менять.
// Get the battery replacement status var batteryStatus = powerSourceTrait.attributes.batReplacementNeeded if batteryStatus { print("Replace the battery.") }
Если батарею может заменить пользователь, в разделе batReplacementDescription
приводится описание батареи, в том числе ее форм-фактор, химический состав и предпочтительный производитель.
Настройки звука
С помощью API Home можно управлять различными настройками аудио.
Включить или выключить микрофон
Чтобы включить или отключить микрофон устройства, обновите атрибут microphoneMuted черты CameraAvStreamManagementTrait с помощью встроенной функции 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
}
}
Как включить или отключить запись аудио
Чтобы включить или отключить аудиозапись на устройстве, обновите атрибут recordingMicrophoneMuted черты CameraAvStreamManagementTrait с помощью встроенной функции 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
}
}
Как настроить громкость колонки
Чтобы изменить громкость динамика устройства, обновите атрибут speakerVolumeLevel черты CameraAvStreamManagementTrait с помощью встроенной функции setSpeakerVolumeLevel:
// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setSpeakerVolumeLevel(value)
}
} catch {
// Error
}
}
Настройки зон слежения
Реализовано в примере приложения для iOS
Свойство ZoneManagement предоставляет интерфейс для управления пользовательскими областями интереса (зонами слежения) на камерах и дверных звонках.
Эти зоны используются для фильтрации обнаружения событий (например, движения человека или транспортного средства) в определенных областях в зоне обзора устройства.
Пользователь настраивает зоны слежения в приложении партнера, выбирая области в поле зрения камеры. Затем эти зоны, заданные пользователем, преобразуются в структуры, используемые этим свойством. Подробнее о том, как настроить и использовать зоны слежения…
Зоны активности обычно определяются с помощью двумерных декартовых координат.
Этот признак содержит TwoDCartesianVertexStruct для вершин и TwoDCartesianZoneStruct для определения зоны (название, вершины, цвет и использование).
Проверьте зоны слежения
Чтобы отобразить зоны слежения, проверьте атрибут zones
ZoneManagement.
let zoneManagementTrait: Google.ZoneManagementTrait self.zones = zoneManagementTrait.attributes.zones ?? []
Как добавить зону активности
Чтобы создать новую зону, используйте команду createTwoDCartesianZone. Эта команда принимает TwoDCartesianZoneStruct, в котором задаются название, вершины, цвет и назначение зоны.
В следующем примере показано, как создать зону под названием "Передний двор" с четырьмя вершинами, окрашенную в цвет лосося (#F439A0) и используемую для обнаружения движения.
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 } }
Как изменить зону активности
Чтобы обновить существующую зону, используйте команду updateTwoDCartesianZone. Для этой команды требуется zoneId и обновленный TwoDCartesianZoneStruct.
let zoneManagementTrait: Google.ZoneManagementTrait let zoneID: UInt16 let zone: Google.ZoneManagementTrait.TwoDCartesianZoneStruct do { _ = try await zoneManagementTrait.updateTwoDCartesianZone( zoneID: zoneID, zone: zone) } catch { // Error }
Как удалить зону активности
Чтобы удалить зону, используйте команду removeZone с определенным значением zoneId.
let zoneManagementTrait: Google.ZoneManagementTrait let zoneID: UInt16 do { _ = try await zoneManagementTrait.removeZone(zoneID: zoneID) } catch { // Error }
Триггеры звуковых событий
Свойство AvStreamAnalysis предоставляет интерфейс для управления триггерами обнаружения событий на камерах и дверных звонках. Триггеры, основанные на распознавании образов (например, людей или автомобилей), могут быть настроены для определенных зон, а звуковые триггеры обычно настраиваются на уровне устройства.
Для распознавания звуков с помощью EventTriggerTypeEnum доступны следующие типы триггеров:
| Режим | Перечисляемое значение | Описание |
|---|---|---|
| Звук | Sound |
Общее распознавание звуков. |
| Речь | PersonTalking |
Распознает речь. |
| Лай собаки | DogBark |
Распознает звуки, издаваемые собаками. |
| Звук бьющегося стекла | GlassBreak |
Распознает звук разбивающегося стекла. |
| Датчик дыма | SmokeAlarm |
Распознает звуки пожарной сигнализации, которые часто имеют звуковой шаблон T3 (три коротких звуковых сигнала с последующей паузой). |
| Датчик угарного газа | CoAlarm |
Обнаруживает сигналы тревоги, связанные с угарным газом, которые обычно распознаются по звуковому сигналу T4 (четыре коротких звуковых сигнала, за которыми следует пауза). |
Как проверить статус распознавания звуков
Чтобы показать пользователю текущее состояние распознавания звуков, необходимо проверить, что поддерживается устройством и что включено аппаратным обеспечением устройства. Проверьте следующие атрибуты:
При разработке для iOS обычно используется черта AvStreamAnalysis, чтобы получить доступ к этим атрибутам.
// 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) ) ) }
Как изменить набор включенных триггеров
Чтобы обновить набор включенных триггеров, используйте команду SetOrUpdateEventDetectionTriggers, которая принимает список структур 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 )
Режимы записи
Реализовано в примере приложения для iOS
Свойство RecordingMode предоставляет интерфейс для управления записью видео и изображений на камерах и дверных звонках. Пользователи могут выбрать непрерывную запись, запись событий или отключить запись (только просмотр трансляции с камеры).
RecordingModeEnum определяет доступные стратегии записи:
| Режим | Перечисляемое значение | Описание |
|---|---|---|
| Отключено | Disabled |
Запись полностью отключена. Используется в основном устаревшими устройствами. |
| Непрерывная видеозапись | Cvr |
Видео записывается круглосуточно. Требуется подписка (например, Google Home Premium). |
| EBR (запись на основе событий) | Ebr |
Запись запускается при обнаружении движения или человека. Продолжительность видео зависит от длительности мероприятия и подписки. |
| ETR (запись по триггеру события) | Etr |
Короткая запись предварительного просмотра (например, 10 секунд), запускаемая событиями. |
| Трансляция с камеры | LiveView |
Запись отключена, но пользователи по-прежнему могут смотреть трансляцию. |
| Картинки | Images |
При возникновении событий вместо видео записываются снимки. |
Проверьте режимы записи
Чтобы посмотреть текущую конфигурацию записи, проверьте атрибуты черты RecordingMode:
supportedRecordingModes– все возможные режимы.availableRecordingModes– режимы, которые можно выбрать.selectedRecordingMode– активный режим.
// 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, ) ) } }
Как изменить режим записи
Перед обновлением убедитесь, что выбранный индекс из атрибута "индекс" supportedRecordingModes присутствует в атрибуте "индекс" availableRecordingModes.
Чтобы обновить выбранный режим, используйте функцию setSelectedRecordingMode, передав индекс выбранного режима:
let recordingModeTrait: Google.RecordingModeTrait let recordingModeID: UInt8 _ = try await recordingModeTrait.update { $0.setSelectedRecordingMode(recordingModeID) }
Другие настройки
Через API Home можно управлять различными другими настройками.
Как включить или отключить ночное видение
Чтобы включить или отключить ночное видение для камеры, используйте TriStateAutoEnum, чтобы обновить атрибут nightVision признака CameraAvStreamManagementTrait с помощью встроенной функции 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
}
}
Как изменить яркость индикатора состояния
Чтобы изменить яркость светодиодного индикатора состояния, используйте ThreeLevelAutoEnum, чтобы обновить атрибут statusLightBrightness признака CameraAvStreamManagementTrait с помощью встроенной функции setStatusLightBrightness:
// Set the LED brightness
func setStatusLightBrightness(
to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setStatusLightBrightness(value)
}
} catch {
// Error
}
}
Как изменить область просмотра камеры
Область просмотра камеры – это то же самое, что и функция масштабирования и кадрирования, описанная в статье о масштабировании и улучшении видео с камеры Nest.
Область просмотра определяется в объекте ViewportStruct, который содержит четыре значения, используемые в качестве координат области просмотра. Координаты определяются следующим образом:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
Значения для ViewportStruct зависят от интерфейса приложения и реализации камеры. Чтобы задать область просмотра видео с камеры, обновите атрибут viewport признака CameraAvStreamManagementTrait с помощью ViewportStruct, используя встроенную функцию 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
}
}
}
Как создать объект TransportOptionsStruct
Для некоторых настроек требуется изменить свойства в TransportOptionsStruct, которые затем передаются в параметры транспорта потокового подключения. В Swift эту структуру необходимо создать до обновления любых свойств.
Используйте эту вспомогательную функцию, чтобы создать структуру для следующих изменений настроек:
- Как настроить чувствительность автоматического выхода из спящего режима
- Как изменить максимальную продолжительность события
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
}
Как включить или отключить аналитику
Каждое устройство может отдельно отправлять подробные аналитические данные в облако Google Home (см. Cloud Monitoring for Home APIs).
Чтобы включить аналитику для устройства, задайте для свойства analyticsEnabled объекта ExtendedGeneralDiagnosticsTrait значение true. Когда вы задаете значение analyticsEnabled, другой параметр, logUploadEnabled, автоматически получает значение true, что позволяет загружать файлы журналов аналитики в облако Google Home.
// Enable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
$0.setAnalyticsEnabled(true)
}
// Disable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
$0.setAnalyticsEnabled(false)
}
Конфигурации транспорта и записи
В этом разделе описаны настройки, связанные с качеством трансляции с камеры и запуском событий. Этими настройками управляет черта PushAvStreamTransport.
Чтение настроек транспорта
В этом разделе рассказывается, как получить текущую конфигурацию с камеры или дверного звонка. Он получает трейт PushAvStreamTransport, находит подключение, которое использовалось для записи, а затем извлекает текущие значения качества пропускной способности, автоматического выхода из спящего режима и максимальной длительности события.
// 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
Как изменить настройки транспорта
В этом разделе рассказывается, как изменить настройки транспорта.
Он создает новую переменную TransportOptionsStruct, содержащую новые значения, а затем использует команду modifyPushTransport, чтобы отправить эти обновленные настройки обратно на устройство и применить их к подключению для записи, найденному на предыдущем шаге.
Чтобы изменить эти настройки, используйте команду modifyPushTransport с 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 )
Как определить качество пропускной способности
Свойство videoStreamId объекта TransportOptionsStruct соответствует определенной конфигурации видеопотока.
Чтобы получить список поддерживаемых видеопотоков, используйте атрибут allocatedVideoStreams, который представляет собой список VideoStreamStructs.
из признака CameraAvStreamManagement для устройства.
Как настроить чувствительность вывода устройства из спящего режима
Свойство motionSensitivity объекта TransportTriggerOptionsStruct соответствует следующим значениям:
| Ярлык | Значение (UInt8) |
|---|---|
| Низкая | 1 |
| Средний | 5 |
| Высокий | 10 |
Как изменить максимальную продолжительность события
Свойство maxDuration объекта TransportMotionTriggerTimeControlStruct соответствует следующим значениям продолжительности UInt32 (в секундах):
- 10, 15, 30, 60, 120, 180
Настройки звонка
Различными настройками дверного звонка можно управлять через Home API.
Как изменить звук звонка
Чтобы изменить звук дверного звонка, сначала получите список звуков звонка, установленных на устройстве, с помощью атрибута installedChimeSounds трейта ChimeTrait:
doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
return chimeSound.chimeID, chimeSound.name
}
Затем обновите атрибут selectedChime признака ChimeTrait, используя встроенную функцию setSelectedChime:
func setDoorbellChime(chimeID: UInt8) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setSelectedChime(chimeID)
}
} catch {
// Error
}
}
Как использовать внешний звонок
Реализовано в примере приложения для iOS
Звонок можно настроить так, чтобы он использовал внешний звонок, например механический, установленный в доме. Это нужно сделать во время установки дверного звонка, чтобы избежать повреждения внешнего звонка.
Чтобы указать тип установленного внешнего звонка, используйте атрибут ExternalChimeType, чтобы обновить атрибут externalChime признака ChimeTrait с помощью встроенной функции 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
}
}
Как изменить длительность внешнего звонка
Продолжительность звонка внешнего звонка в секундах можно настроить с помощью API Google Home. Если внешний звонок поддерживает настройку длительности, пользователь может захотеть ее задать.
Значение зависит от характеристик внешнего звонка и рекомендованной длительности сигнала.
Чтобы изменить продолжительность внешнего звукового сигнала, обновите атрибут externalChimeDurationSeconds признака ChimeTrait с помощью встроенной функции setExternalChimeDurationSeconds:
// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
do {
_ = try await doorbellChimeTrait.update {
$0.setExternalChimeDuration(value)
}
} catch {
// Error
}
}
Как включить тему звонка
Реализовано в примере приложения для iOS
У некоторых дверных звонков есть мелодии, которые доступны пользователям только в течение ограниченного времени. Например, мелодии, связанные с праздниками. Это называется темами звонков.
Чтобы узнать, какие темы доступны пользователю, создайте фильтр временного интервала и примените его для фильтрации результатов команды getAvailableThemes из черты ChimeThemes. В результате будет показан список доступных тем, в том числе их названия.
В следующем примере показано, как отфильтровать список.
Тема считается активной, если текущее время находится в диапазоне между временем начала и окончания (значения startTimeSeconds и endTimeSeconds соответственно). Если время начала не задано, считается, что правило активно с начала времен. Если время окончания не задано, правило будет действовать бессрочно. Если оба параметра отсутствуют, тема всегда активна.
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)
}
}
}
Если вы знаете название нужной темы, например Christmas, вы можете выбрать ее с помощью функции setSelectedTimeboxedThemeName() в рамках свойства ChimeThemes ChimeThemes.
private func setChimeTheme(to value: String) async throws {
_ = try await chimeThemeTrait.update {
$0.setSelectedTimeboxedThemeName(value)
}
}
Настройки объявлений для посетителей
Вы можете запрашивать и изменять настройки уведомлений о посетителях для дверных звонков с помощью черты VisitorAnnouncement API Home. Этот признак определяет, будет ли объявляться о присутствии посетителя на умных колонках или дисплеях Google, когда кто-то звонит в дверной звонок.
В примере ниже показано, как проверить, включены ли уведомления о посетителях, и как изменить эту настройку.
let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled let value: Bool _ = try await self.visitorAnnouncementTrait?.update { $0.setVisitorAnnouncementsEnabled(value) }
Как списать устройство
Чтобы удалить дверной звонок из структуры, вызовите метод device.decommission(). При отключении пользователю показывается управляемый Google экран подтверждения с предупреждением о том, что все записанные видео, архив событий, клипы и данные библиотеки знакомых лиц будут безвозвратно удалены из структуры.
Подробные инструкции и примеры кода приведены в статье Как удалить устройство.