Typ urządzenia Camera jest implementowany za pomocą 2 cech:PushAvStreamTransportTrait, która obsługuje transport strumieni audio i wideo za pomocą protokołów opartych na wysyłaniu, oraz WebRtcLiveViewTrait, która umożliwia sterowanie transmisjami na żywo i funkcją talkback.
Przed użyciem jakichkolwiek funkcji lub próbą zaktualizowania atrybutów zawsze sprawdzaj, czy urządzenie obsługuje atrybuty i polecenia. Więcej informacji znajdziesz w artykule Sterowanie urządzeniami na iOS.
| Typ urządzenia interfejsów Home API | Cechy | Przykładowa aplikacja w Swift | Przypadek użycia |
|---|---|---|---|
Aparat
Urządzenie, które robi zdjęcia lub nagrywa filmy. Kamery mogą oferować dostępne transmisje na żywo, rozmowę dwukierunkową lub wykrywanie zdarzeń. |
Wymagane cechy google PushAvStreamTransportTrait google WebRtcLiveViewTrait |
Aparat |
Rozpoczynanie transmisji na żywo
Aby rozpocząć transmisję na żywo, wyślij ciąg protokołu SDP (Session Description Protocol) 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
Transmisje na żywo mają z góry określony czas trwania, po którym wygasają. Aby wydłużyć czas trwania aktywnego strumienia, wyślij prośbę o przedłużenie 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
Aby uruchomić TalkBack, wywołaj metodę startTalkback(mediaSessionId:optionalArgsProvider:) cechy
WebRtcLiveViewTrait.
Aby zatrzymać, kliknij 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)")
}
}
Włączanie i wyłączanie możliwości nagrywania
Aby włączyć funkcję nagrywania kamery, przekaż wartość
TransportStatusEnum.Active
do metody
PushAvStreamTransportTrait
cechy
setTransportStatus(transportStatus:optionalArgsProvider:). Aby wyłączyć możliwość nagrywania, przekaż wartość
TransportStatusEnum.Inactive.
W poniższym przykładzie umieszczamy te wywołania w jednym wywołaniu, które używa Boolean, aby włączać i wyłączać możliwość 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 nagrywania przez kamerę jest równoznaczne z włączeniem lub wyłączeniem wideo z kamery. Gdy wideo z kamery jest włączone, kamera nagrywa (na potrzeby zdarzeń i powiązanych klipów).
Gdy funkcja nagrywania jest wyłączona (wideo z kamery jest wyłączone):
- Kamera może nadal być widoczna 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 kamery jest włączona, sprawdź, czy są aktywne jakiekolwiek połączenia. Poniższy przykład definiuje 2 funkcje, które to umożliwiają:
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
}
Ustawienia dźwięku
Różnymi ustawieniami dźwięku kamery można sterować za pomocą interfejsów API Home.
Włączanie i wyłączanie mikrofonu
Aby włączyć lub wyłączyć mikrofon urządzenia, zaktualizuj atrybut microphoneMuted
cechy CameraAvStreamManagementTrait za pomocą 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
}
}
Dostosowywanie głośności głośnika
Aby dostosować głośność głośnika urządzenia, zaktualizuj atrybutspeakerVolumeLevel
cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcjisetSpeakerVolumeLevel:
// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setSpeakerVolumeLevel(value)
}
} catch {
// Error
}
}
Inne ustawienia
Za pomocą interfejsów API Home można sterować różnymi innymi ustawieniami kamery.
Zmienianie orientacji obrazu
Orientację obrazu z kamery (filmu) można obracać. Film można obrócić tylko o 180 stopni.
Aby zmienić orientację obrazu z kamery, zaktualizuj atrybut imageRotation cechy CameraAvStreamManagementTrait za pomocą wbudowanej funkcji setImageRotation:
// Change the camera's image orientation
// Value must be 0 or 180
func setImageRotation(to value: UInt16) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setImageRotation(value)
}
} catch {
// Error
}
}
Włączanie i wyłączanie widzenia w nocy
Aby włączyć lub wyłączyć widzenie w nocy w przypadku 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
}
}
Zmiana jasności diody LED stanu
Aby zmienić jasność diody LED stanu, użyj
ThreeLevelAutoEnum
do zaktualizowania atrybutu
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 widocznego obszaru kamery
Widok z kamery jest taki sam jak w przypadku funkcji powiększania i kadrowania opisanej w artykule pomocy Powiększanie i ulepszanie obrazu z kamery Nest.
Obszar wyświetlania jest zdefiniowany w ViewportStruct, który zawiera 4 wartości używane jako współrzędne obszaru wyświetlania. Współrzędne są zdefiniowane w ten sposób:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
Określanie wartości parametru ViewportStruct zależy od interfejsu aplikacji i implementacji kamery. Aby ustawić pole widzenia kamery, zaktualizuj atrybut viewport cechy CameraAvStreamManagementTrait za pomocą funkcji 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 TransportOptionsStruct, które są następnie przekazywane do opcji transportu połączenia strumieniowego. W przypadku języka Swift tę strukturę należy wygenerować przed zaktualizowaniem jakichkolwiek właściwości.
Użyj tej funkcji pomocniczej, aby wygenerować strukturę do wykorzystania przy wprowadzaniu tych zmian 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
}
Dostosowywanie czułości wybudzania urządzenia
Czułość wybudzania urządzenia służy do oszczędzania baterii poprzez zmniejszenie zakresu, w którym urządzenie może wykrywać aktywność, i wydłużenie czasu wybudzania po wykryciu tej aktywności.
W interfejsach Home API można to ustawić za pomocą właściwości motionSensitivity elementu triggerOptions w transportOptions urządzenia. Te opcje są zdefiniowane w PushAvStreamTransportTrait dla każdego urządzenia.
Czułość wybudzania można ustawić tylko na te wartości:
- 1 = Niski
- 5 = Średni
- 10 = Wysoki
Proces aktualizacji polega na znalezieniu konfiguracji transportu dla aktywnych strumieni nagrywania za pomocą polecenia findTransport, a następnie zmodyfikowaniu konfiguracji za pomocą nowej wartości czułości za pomocą polecenia modifyPushTransport.
Polecenie modifyPushTransport wymaga przekazania pełnego TransportOptionsStruct, więc najpierw musisz skopiować istniejące wartości z bieżącej konfiguracji. Aby to zrobić, zapoznaj się z sekcją Generowanie TransportOptionsStruct dla funkcji pomocniczej.
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
}
}
Dostosowywanie maksymalnego czasu trwania zdarzenia
Maksymalna długość zdarzenia to czas, przez jaki kamera będzie nagrywać klip w przypadku zdarzenia. Za pomocą interfejsów Home API można skonfigurować dla każdego urządzenia te same długości, co w przypadku Google Home app (GHA), w odstępach sekund:
- 10 sekund
- 15 sekund
- 30 sekund
- 60 sekund (1 minuta)
- 120 sekund (2 minuty)
- 180 sekund (3 minuty)
W interfejsach Home API można to ustawić za pomocą właściwości motionTimeControl elementu triggerOptions w transportOptions urządzenia. Te opcje są zdefiniowane w PushAvStreamTransportTrait dla każdego urządzenia.
Aby zaktualizować konfigurację, znajdź konfigurację transportu dla aktywnych strumieni nagrywania za pomocą polecenia findTransport, a następnie zmodyfikuj konfigurację, podając nową wartość długości zdarzenia, za pomocą polecenia modifyPushTransport.
Polecenie modifyPushTransport wymaga przekazania pełnego TransportOptionsStruct, więc najpierw musisz skopiować istniejące wartości z bieżącej konfiguracji. Aby to zrobić, zapoznaj się z sekcją Generowanie TransportOptionsStruct dla funkcji pomocniczej.
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
}
}