راهنمای دستگاه دوربین برای iOS

نوع دستگاه «دوربین» بااستفاده از سه مشخصه پیاده‌سازی می‌شود: PushAvStreamTransportTrait، که انتقال جاری‌سازی صوتی و تصویری را بااستفاده از پروتکل‌های مبتنی بر فشار مدیریت می‌کند، WebRtcLiveViewTrait، که امکان کنترل جاری‌سازی‌های زنده و مکالمه را فراهم می‌کند، و CameraSnapshotTrait، که پیش‌نمایش‌های حافظه نهان و ضبط‌های فوری زنده را ارائه می‌دهد.

همیشه قبل‌از استفاده از هر ویژگی یا تلاش برای به‌روزرسانی مشخصه‌ها، پشتیبانی از مشخصه و فرمان را برای دستگاه بررسی کنید. برای اطلاعات بیشتر، کنترل دستگاه‌ها در iOS را ببینید.

نوع دستگاه Home APIs ویژگی‌ها برنامه نمونه Swift کاربرد

دوربین

GoogleCameraDeviceType

home.matter.6006.types.0158

دستگاهی که تصاویر ثابت یا ویدیو ضبط می‌کند. دوربین‌ها ممکن است دارای جاری‌سازی زنده دسترس‌پذیر، صحبت دوطرفه، یا رویدادهای تشخیص باشند.

ویژگی‌های الزامی
     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

دریافت جدیدترین زمان تماس ابری دستگاه

برای پیدا کردن جدیدترین زمانی که دستگاه با فضای ابری ارتباط داشته است، از مشخصه 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 cameraConnectivity = cameraDeviceType.metadata.sourceConnectivity.connectivityState

درصورت وجود انواع دستگاه مختلط و عدم اتصال به اینترنت، ممکن است وضعیت partiallyOnline مشاهده شود. ممکن است ویژگی‌های استاندارد Matter به‌دلیل مسیریابی محلی همچنان آنلاین باشند، اما ویژگی‌های مبتنی بر ابر آفلاین خواهند بود.

دریافت نشانی IP دستگاه

برای پیدا کردن نشانی IP دستگاه، از مشخصه networkInterfaces در GeneralDiagnosticsTrait استفاده کنید. نشانی‌ها به‌عنوان Data شیء برگردانده می‌شوند که می‌توانید آن‌ها را بااستفاده از چارچوب Network به رشته‌های استاندارد IPv4 یا IPv6 قالب‌بندی کنید:

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» پیاده‌سازی شده است   

برای شروع TalkBack، با روش WebRtcLiveViewTrait ویژگی startTalkback(mediaSessionId:optionalArgsProvider:) تماس بگیرید. برای توقف، از 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 را به 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
}

دریافت عکس‌های آنی دوربین

   در «برنامه نمونه برای iOS» پیاده‌سازی شده است   

از مشخصه CameraSnapshot برای بازیابی عکس‌های آنی تصویر ثابت از دوربین استفاده کنید. این نماگرفت‌ها برای چندین سناریو مفید هستند:

  • به‌عنوان کاشی جای‌بان در رابط کاربری درحالی‌که پخش زنده WebRTC درحال بارگیری است.
  • به‌عنوان تصویر پیش‌نمایش ثابت که با تعامل کاربر به جاری‌سازی زنده ارتقا می‌یابد.
  • به‌عنوان بوم پس‌زمینه برای طراحی و پیکربندی مناطق فعالیت سفارشی.

ویژگی CameraSnapshot دو روش برای واکشی کردن نماهای فوری ارائه می‌دهد، بسته به اینکه به نمای فوری ذخیره‌شده برای پردازش سریع نیاز دارید یا به نمای فوری زنده درخواستی.

دریافت عکس آنی پیش‌نمایش ذخیره‌شده

عکس آنی پیش‌نمایش تصویری ذخیره‌شده در حافظه نهان است که «کیت توسعه نرم‌افزاری» می‌تواند بدون روشن کردن دوربین آن را بازیابی کند. این سریع‌ترین روش برای واکشی تصویر ثابت است و برای صفحات نمای کلی دوربین یا شبکه‌های داشبورد ایده‌آل است.

برای دریافت چیدمان پیش‌نمایش، مشخصه ویژگی 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
}

بسته به پیکربندی و فعالیت دوربین، نشانی وب پیش‌نمایش به تصویر ذخیره‌شده در حافظه نهان تولیدشده از فیلم ویدیویی اخیر (اولین قاب 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» پیاده‌سازی شده است   

همه نشانی‌های وب نمای فوری به رسانه‌های امن اشاره می‌کنند و برای دامنه Home APIs v2 به کد OAuth 2.0 نیاز دارند. برای بارگیری و پرداز کردن تصاویر، کد 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
  }
}

تنظیمات باتری

تنظیمات مختلف باتری را می‌توان ازطریق Home APIs کنترل کرد.

اولویت مصرف باتری را تنظیم کنید

با تنظیم تراز انرژی می‌توانید مبادله بین عمر باتری و عملکرد دستگاه را پیکربندی کنید. می‌توانید نمایه‌های باتری مختلفی مثل «طولانی»، «متعادل»، و «عملکرد» ایجاد کنید و بین آن‌ها جابه‌جا شوید.

این ویژگی با به‌روزرسانی مشخصه 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 باتری را توصیف می‌کند، ازجمله اطلاعاتی مثل عامل شکل، شیمی، و سازنده ترجیحی.

تنظیمات صوتی

تنظیمات مختلف صدا را می‌توان ازطریق Home APIs کنترل کرد.

روشن یا خاموش کردن میکروفون

برای روشن یا خاموش کردن میکروفون دستگاه، 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 دردسترس است:

حالت مقدار Enum شرح
صدا Sound تشخیص صدای عمومی.
صحبت کردن یک شخص PersonTalking گفتار را تشخیص می‌دهد.
پارس سگ DogBark صدای سگ را تشخیص می‌دهد.
شکستن شیشه GlassBreak صدای شکستن شیشه را تشخیص می‌دهد.
هشدار دود SmokeAlarm زنگ‌های هشدار دود را تشخیص می‌دهد، که اغلب با الگوی شنیداری T3 (سه بوق کوتاه و سپس یک مکث) شناخته می‌شوند.
هشدار مونوکسیدکربن CoAlarm هشدارهای کربن منوکسید (CO) را تشخیص می‌دهد، که معمولاً با الگوی شنیداری 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 استراتژی‌های ضبط دردسترس را تعریف می‌کند:

حالت مقدار Enum شرح
غیرفعال Disabled ضبط کاملاً غیرفعال است. عمدتاً توسط دستگاه‌های قدیمی استفاده می‌شود.
CVR (ضبط ویدیو پیوسته) Cvr ویدیو به‌صورت شبانه‌روزی ضبط می‌شود. به اشتراک نیاز دارد (برای نمونه، Google Home Premium.
EBR (ضبط براساس رویداد) Ebr ضبط با رویدادها (شخص، حرکت) راه‌اندازی می‌شود. طول ویدیو به مدت رویداد و اشتراک بستگی دارد.
ETR (ضبط رویداد-راه‌اندازی‌شده) Etr ضبط پیش‌نمایش کوتاه (برای مثال، ۱۰ ثانیه) راه‌اندازی‌شده توسط رویدادها.
نمای زنده 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 APIs کنترل کرد.

تغییر جهت تصویر

جهت تصویر دوربین (ویدیو) را می‌توان چرخاند. ویدیو فقط می‌تواند ۱۸۰ درجه بچرخد.

برای تغییر جهت تصویر دوربین، 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
}

فعال یا غیرفعال کردن تجزیه‌وتحلیل

هر دستگاه می‌تواند به‌صورت جداگانه موافقت کند که داده‌های تجزیه‌وتحلیل دقیق را به ابر Google 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)
}

پیکربندی‌های انتقال و ضبط

این بخش تنظیمات مربوط به کیفیت جاری‌سازی دوربین و راه‌اندازی رویداد را پوشش می‌دهد. این تنظیمات توسط 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 مدت زمان زیر (به ثانیه) مطابقت دارد:

  • ۱۰، ۱۵، ۳۰، ۶۰، ۱۲۰، ۱۸۰

ازکار انداختن دستگاه

برای برداشتن دوربین از ساختار، با device.decommission() تماس بگیرید. ازکار انداختن باعث می‌شود صفحه تأیید مدیریت‌شده توسط Google به کاربر نمایش داده شود و به او هشدار دهد که همه سابقه ویدیویی شبانه‌روزی ضبط‌شده، سابقه رویداد، کلیپ‌ها، و داده‌های کتابخانه چهره آشنا برای همیشه در سراسر ساختار حذف خواهد شد.

برای دستورالعمل‌های دقیق و نمونه‌های کد، به برداشتن دستگاه مراجعه کنید.