دليل أجهزة الكاميرا على أجهزة iOS

يتم تنفيذ نوع جهاز الكاميرا باستخدام سمتَين: PushAvStreamTransportTrait التي تعالج نقل بث الصوت والفيديو باستخدام بروتوكولات تستند إلى الإرسال، و WebRtcLiveViewTrait التي تتيح التحكّم في البث المباشر والمحادثة.

يُرجى دائمًا التحقّق من توفّر سمة أو أمر لجهاز قبل استخدام أي ميزات أو محاولة تعديل السمات. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة التحكّم في الأجهزة على iOS.

نوع جهاز واجهات برمجة تطبيقات Home الصفات نموذج تطبيق Swift حالة الاستخدام

الكاميرا

GoogleCameraDeviceType

home.matter.6006.types.0158

جهاز يلتقط صورًا ثابتة أو فيديو قد تتضمّن الكاميرات بثًا مباشرًا يمكن الوصول إليه أو محادثة ثنائية الاتجاه أو أحداث رصد.

السمات المطلوبة
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

الكاميرا

الحصول على معلومات أساسية عن جهاز

تتضمّن السمة BasicInformation معلومات مثل اسم المورّد ورقم تعريف المورّد ورقم تعريف المنتج، واسم المنتج (يتضمّن معلومات الطراز) وإصدار البرنامج، والرقم التسلسلي للجهاز:

// [START get_device_information]
let vendorName = basicInfoTrait.attributes.vendorName!
let vendorID = basicInfoTrait.attributes.vendorID!
let productID = basicInfoTrait.attributes.productID!
let productName = basicInfoTrait.attributes.productName!
let softwareVersion = basicInfoTrait.attributes.softwareVersion!
let serialNumber = basicInfoTrait.attributes.serialNumber!
// [END get_device_information]

الحصول على آخر وقت تم فيه التواصل مع السحابة الإلكترونية للجهاز

للعثور على آخر وقت تواصل فيه الجهاز مع السحابة الإلكترونية، استخدِم السمة lastContactTimestampفي السمة ExtendedGeneralDiagnostics:

if let lastContactTimeStamp = extendedGeneralDiagnosticsTrait.attributes.lastContactTimestamp {
  self.lastContactTime = Date(timeIntervalSince1970: Double(lastConnectedTimeStamp))
}

التحقّق من الاتصال بجهاز

يتم التحقّق من الاتصال بجهاز على مستوى نوع الجهاز لأنّ بعض الأجهزة تتيح أنواعًا متعددة من الأجهزة. الحالة التي يتم عرضها هي مزيج من حالات الاتصال لجميع السمات على هذا الجهاز.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

قد تظهر حالة partiallyOnline في حالة أنواع الأجهزة المختلطة عندما لا يتوفّر اتصال بالإنترنت. قد تظل السمات العادية في MatterMatter متصلة بالإنترنت بسبب التوجيه المحلي، ولكن ستكون السمات المستندة إلى السحابة الإلكترونية غير متصلة بالإنترنت.

بدء بث مباشر

لبدء بث مباشر، أرسِل سلسلة بروتوكول وصف الجلسة (SDP) إلى WebRtcLiveViewTrait في السمة startLiveView(offerSdp:) ، التي تعرض ثلاث قيم:

  • بروتوكول وصف الجلسة (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
  }
}

تمديد بث مباشر

تكون مدة البث المباشر محددة مسبقًا، وبعدها تنتهي صلاحيته. لإطالة مدة البث النشط، أرسِل طلب تمديد باستخدام 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
  }
}

بدء المحادثة وإيقافها

لبدء المحادثة، استخدِم طريقة 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)")
  }
}

تفعيل إمكانية التسجيل وإيقافها

لتفعيل إمكانية التسجيل في الكاميرا، مرِّر TransportStatusEnum.Active إلى السمة PushAvStreamTransportTrait في طريقة setTransportStatus(transportStatus:optionalArgsProvider:). لإيقاف إمكانية التسجيل، مرِّرها 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
}

إعدادات البطارية

يمكن التحكّم في إعدادات البطارية المختلفة من خلال واجهات برمجة تطبيقات 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)
  }
}

تفعيل ميزة "توفير شحن البطارية" تلقائيًا

لضبط هذه الميزة، عدِّل السمة currentLowPowerModeSensitivity في السمة EnergyPreference. تستخدم هذه السمة فهرسًا لاختيار مستوى الحساسية، حيث يمثّل 0 عادةً Disabled ويمثّل 1 Enabled أو Automatic.

private func setAutoBatterySaver(to value: Bool) async throws {
  _ = try await energyPreferenceTrait.update {
    $0.setCurrentLowPowerModeSensitivity(value ? 1 : 0)
  }
}

الحصول على حالة شحن البطارية

للحصول على حالة الشحن الحالية للجهاز (جارٍ الشحن أو مشحونة بالكامل أو لا يتم الشحن)، استخدِم الـ 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
}

إعدادات الصوت

يمكن التحكّم في إعدادات الصوت المختلفة من خلال واجهات برمجة تطبيقات 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
  }
}

إعدادات منطقة النشاط

توفّر السمة 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
)

أوضاع التسجيل

توفّر السمة RecordingMode واجهة لإدارة سلوك تسجيل الفيديو والصور على أجهزة الكاميرا وأجراس الباب. تسمح هذه السمة للمستخدمين بالاختيار بين التسجيل المتواصل أو التسجيل فقط عند رصد حدث أو إيقاف التسجيل بالكامل (العرض المباشر فقط).

يحدّد RecordingModeEnum استراتيجيات التسجيل المتاحة:

الوضع قيمة التعداد الوصف
غير مُفعَّلة Disabled تم إيقاف التسجيل بالكامل. يُستخدم بشكل أساسي من قِبل الأجهزة القديمة.
التسجيل المتواصل (CVR) Cvr يتم تسجيل الفيديو على مدار الساعة. يتطلّب هذا الإجراء اشتراكًا (على سبيل المثال، Google Home Premium).
التسجيل المستند إلى الأحداث (EBR) Ebr يتم بدء التسجيل من خلال الأحداث (الشخص أو الحركة). تعتمد مدة الفيديو على مدة الحدث والاشتراك.
ETR (ETR) Etr تسجيل معاينة قصيرة (على سبيل المثال، 10 ثوانٍ) يتم بدءها من خلال الأحداث
العرض المباشر LiveView تم إيقاف التسجيل، ولكن لا يزال بإمكان المستخدمين الوصول إلى البث المباشر.
الصور الثابتة Images يتم تسجيل اللقطات بدلاً من الفيديو عند وقوع الأحداث.

الاطّلاع على أوضاع التسجيل

لعرض إعدادات التسجيل الحالية، اطّلِع على سمات السمة RecordingMode:

// 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)
}

إعدادات أخرى

يمكن التحكّم في إعدادات أخرى مختلفة من خلال واجهات برمجة تطبيقات Home.

تغيير اتجاه الصورة

يمكن تدوير اتجاه صورة الكاميرا (الفيديو). لا يمكن تدوير الفيديو إلا بمقدار 180 درجة.

لتغيير اتجاه صورة الكاميرا، عدِّل السمة imageRotation في السمة CameraAvStreamManagementTrait باستخدام الدالة المضمّنة 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
  }
}

تفعيل ميزة "الرؤية الليلية" أو إيقافها

لتفعيل ميزة "الرؤية الليلية" أو إيقافها للكاميرا، استخدِم 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
  }
}

تغيير سطوع مؤشر LED للحالة

لتغيير سطوع مؤشر LED للحالة، استخدِم 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
}

ضبط حساسية أجهزة الاستشعار لتشغيل الجهاز

تُستخدم حساسية أجهزة الاستشعار لتشغيل الكاميرا للحفاظ على البطارية من خلال تقليل النطاق الذي يمكن للجهاز من خلاله استشعار النشاط وزيادة وقت التنبيه بعد رصد هذا النشاط.

في واجهات برمجة تطبيقات Home، يمكن ضبط ذلك باستخدام السمة motionSensitivity في triggerOptions في transportOptions للجهاز. يتم تحديد هذه الخيارات ضمن السمة PushAvStreamTransportTrait لكل جهاز.

لا يمكن ضبط حساسية أجهزة الاستشعار لتشغيل الكاميرا إلا على القيم التالية:

  • ‫1 = منخفض
  • ‫5 = متوسط
  • ‫10 = مرتفع

تتم عملية التعديل من خلال العثور على إعدادات النقل لعمليات بث التسجيل النشطة باستخدام findTransport ، ثم تعديل الإعدادات باستخدام قيمة الحساسية الجديدة باستخدام modifyPushTransport.

يتطلّب الأمر modifyPushTransport تمرير TransportOptionsStruct بالكامل، لذا عليك أولاً نسخ القيم الحالية من الإعدادات الحالية. يُرجى الاطّلاع على إنشاء TransportOptionsStruct للحصول على دالة مساعدة لإجراء ذلك.

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
  }
}

ضبط الحد الأقصى لمدة الحدث

الحد الأقصى لمدة الحدث هو المدة التي ستسجّل فيها الكاميرا مقطعًا لحدث معيّن. من خلال واجهات برمجة تطبيقات Home، يمكن ضبط ذلك لكل جهاز، بنفس المدد التي يتم ضبطها من خلال Google Home app (GHA)، بفواصل زمنية بالثواني:

  • 10 ثوانٍ
  • ‫15 ثانية
  • ‫30 ثانية
  • 60 ثانية (دقيقة واحدة)
  • 120 ثانية (دقيقتان)
  • 180 ثانية (3 دقائق)

في واجهات برمجة تطبيقات Home، يمكن ضبط ذلك باستخدام السمة motionTimeControl في triggerOptions في transportOptions للجهاز. يتم تحديد هذه الخيارات ضمن السمة PushAvStreamTransportTrait لكل جهاز.

تتم عملية التعديل من خلال العثور على إعدادات النقل لعمليات بث التسجيل النشطة باستخدام findTransport ، ثم تعديل الإعدادات باستخدام قيمة مدة الحدث الجديدة باستخدام modifyPushTransport.

يتطلّب الأمر modifyPushTransport تمرير TransportOptionsStruct بالكامل، لذا عليك أولاً نسخ القيم الحالية من الإعدادات الحالية. يُرجى الاطّلاع على إنشاء TransportOptionsStruct للحصول على دالة مساعدة لإجراء ذلك.

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
  }
}

تفعيل ميزة "الإحصاءات" أو إيقافها

يمكن لكل جهاز الموافقة بشكل فردي على إرسال بيانات إحصاءات مفصّلة إلى سحابة Google Home (يُرجى الاطّلاع على مقالة المراقبة السحابية لواجهات برمجة تطبيقات Home).

لتفعيل ميزة "الإحصاءات" لجهاز، اضبط السمة 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)
}