iOS এর জন্য ডোরবেল ডিভাইস নির্দেশিকা

ডোরবেল ডিভাইস টাইপটি দুটি ট্রেইট ব্যবহার করে প্রয়োগ করা হয়েছে: PushAvStreamTransportTrait , যা পুশ-ভিত্তিক প্রোটোকল ব্যবহার করে অডিও এবং ভিডিও স্ট্রিম পরিবহন পরিচালনা করে, এবং WebRtcLiveViewTrait , যা লাইভস্ট্রিম এবং টকব্যাক নিয়ন্ত্রণ করার ক্ষমতা প্রদান করে।

যেকোনো বৈশিষ্ট্য ব্যবহার করার বা অ্যাট্রিবিউট আপডেট করার চেষ্টা করার আগে, ডিভাইসটির অ্যাট্রিবিউট এবং কমান্ড সমর্থনের বিষয়টি সর্বদা যাচাই করে নিন। ডিভাইস নিয়ন্ত্রণ দেখুন।iOS আরও তথ্যের জন্য।

হোম এপিআই ডিভাইসের ধরন বৈশিষ্ট্য সুইফট নমুনা অ্যাপ ব্যবহারের ক্ষেত্র

ডোরবেল

Google Doorbell DeviceType

home.matter.6006.types.0113

দরজার বাইরে থাকা একটি বোতাম দ্বারা চালিত যন্ত্র, যা দরজার অপর পাশে থাকা কোনো ব্যক্তির দৃষ্টি আকর্ষণের জন্য শ্রবণযোগ্য এবং/অথবা দৃশ্যমান সংকেত দেয়। ডোরবেলে সহজলভ্য লাইভস্ট্রিম, দ্বিমুখী টকব্যাক বা ডিটেকশন ইভেন্টের মতো বৈশিষ্ট্য থাকতে পারে।

প্রয়োজনীয় বৈশিষ্ট্য
google PushAvStreamTransportTrait
গুগল 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]

ডিভাইস ক্লাউড যোগাযোগের সর্বশেষ সময় পান

ডিভাইসটি সর্বশেষ কখন ক্লাউডের সাথে সংযোগ স্থাপন করেছিল তা জানতে, ExtendedGeneralDiagnostics ট্রেইটের lastContactTimestamp অ্যাট্রিবিউটটি ব্যবহার করুন:

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

একটি ডিভাইসের সংযোগ পরীক্ষা করুন

একটি ডিভাইসের কানেক্টিভিটি আসলে ডিভাইস টাইপ লেভেলে চেক করা হয়, কারণ কিছু ডিভাইস একাধিক ডিভাইস টাইপ সাপোর্ট করে। যে স্টেটটি রিটার্ন করা হয়, তা হলো সেই ডিভাইসের সমস্ত ট্রেইটের কানেক্টিভিটি স্টেটগুলোর একটি সমন্বয়।

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

ইন্টারনেট সংযোগ না থাকলে, বিভিন্ন ধরনের ডিভাইসের ক্ষেত্রে একটি partiallyOnline অবস্থা দেখা যেতে পারে। লোকাল রাউটিংয়ের কারণে Matter স্ট্যান্ডার্ড বৈশিষ্ট্যগুলো অনলাইন থাকতে পারে, কিন্তু ক্লাউড-ভিত্তিক বৈশিষ্ট্যগুলো অফলাইন থাকবে।

একটি লাইভস্ট্রিম শুরু করুন

একটি লাইভস্ট্রিম শুরু করতে, 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
  }
}

টকব্যাক শুরু এবং বন্ধ করুন

টকব্যাক শুরু করতে, 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)")
  }
}

রেকর্ডিং ক্ষমতা চালু এবং বন্ধ করুন

ক্যামেরার রেকর্ডিং ক্ষমতা চালু করতে, PushAvStreamTransportTrait ট্রেইটের setTransportStatus(transportStatus:optionalArgsProvider:) মেথডে TransportStatusEnum.Active পাস করুন। রেকর্ডিং ক্ষমতা বন্ধ করতে, এতে 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
}

ব্যাটারি সেটিংস

হোম এপিআই-এর মাধ্যমে ব্যাটারির বিভিন্ন সেটিংস নিয়ন্ত্রণ করা যায়।

ব্যাটারি ব্যবহারের পছন্দ সেট করুন

এনার্জি ব্যালেন্স সেট করার মাধ্যমে আপনি একটি ডিভাইসের জন্য ব্যাটারি লাইফ এবং পারফরম্যান্সের মধ্যে ভারসাম্য নির্ধারণ করতে পারেন। আপনি "এক্সটেন্ডেড," "ব্যালেন্সড," এবং "পারফরম্যান্স"-এর মতো বিভিন্ন ব্যাটারি প্রোফাইল তৈরি করতে এবং সেগুলোর মধ্যে পরিবর্তন করতে পারেন।

এই ফিচারটি EnergyPreference ট্রেইটের currentEnergyBalance অ্যাট্রিবিউট আপডেট করার মাধ্যমে প্রয়োগ করা হয়। অ্যাট্রিবিউটটি একটি পূর্ণসংখ্যা ইনডেক্স গ্রহণ করে, যা ডিভাইসের energyBalances তালিকায় সংজ্ঞায়িত একটি নির্দিষ্ট প্রোফাইলের সাথে সঙ্গতিপূর্ণ (উদাহরণস্বরূপ, EXTENDED এর জন্য 0 , BALANCED এর জন্য 1 , এবং PERFORMANCE জন্য 2 )।

currentEnergyBalance এর মান null বোঝা যায় যে ডিভাইসটি একটি কাস্টম প্রোফাইল ব্যবহার করছে। এটি একটি পঠন-যোগ্য অবস্থা।

নিচে 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)
  }
}

স্বয়ংক্রিয় ব্যাটারি সেভার চালু করুন

এই ফিচারটি কনফিগার করতে, EnergyPreference ট্রেইটের currentLowPowerModeSensitivity অ্যাট্রিবিউটটি আপডেট করুন। এই অ্যাট্রিবিউটটি একটি সেনসিটিভিটি লেভেল নির্বাচন করার জন্য একটি ইনডেক্স ব্যবহার করে, যেখানে 0 সাধারণত Disabled এবং 1 Enabled বা Automatic বোঝায়।

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

ব্যাটারি চার্জিং অবস্থা জানুন

ডিভাইসটির বর্তমান চার্জিং অবস্থা (চার্জ হচ্ছে, সম্পূর্ণ চার্জ হয়েছে, বা চার্জ হচ্ছে না) জানতে, PowerSource ট্রেইটের batChargeState অ্যাট্রিবিউটটি ব্যবহার করুন।

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

ব্যাটারির লেভেল জানুন

বর্তমান ব্যাটারি লেভেল জানতে, PowerSource ট্রেইটের batChargeLevel অ্যাট্রিবিউটটি ব্যবহার করুন। লেভেলটি হয় 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"
}

শক্তির উৎসটি নিন

ডিভাইসটি কোন পাওয়ার সোর্স ব্যবহার করছে তা নির্ধারণ করতে, PowerSource ট্রেইটের BatPresent এবং wiredPresent অ্যাট্রিবিউটগুলো ব্যবহার করুন।

if powerSourceTrait.attributes.wiredPresent ?? false {
  self.powerSourceType = .wired
} else if powerSourceTrait.attributes.batPresent ?? false {
  self.powerSourceType = .battery
} else {
  self.powerSourceType = nil
}

অডিও সেটিংস

হোম এপিআই-এর মাধ্যমে বিভিন্ন অডিও সেটিংস নিয়ন্ত্রণ করা যায়।

মাইক্রোফোন চালু বা বন্ধ করুন

ডিভাইসের মাইক্রোফোন চালু বা বন্ধ করতে, বিল্ট-ইন setMicrophoneMuted ফাংশনটি ব্যবহার করে CameraAvStreamManagementTrait ট্রেইটের microphoneMuted অ্যাট্রিবিউটটি আপডেট করুন:

// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

অডিও রেকর্ডিং চালু বা বন্ধ করুন

ডিভাইসটির জন্য অডিও রেকর্ডিং চালু বা বন্ধ করতে, বিল্ট-ইন setRecordingMicrophoneMuted ফাংশনটি ব্যবহার করে CameraAvStreamManagementTrait ট্রেইটের recordingMicrophoneMuted অ্যাট্রিবিউটটি আপডেট করুন:

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

স্পিকারের ভলিউম সামঞ্জস্য করুন।

ডিভাইসের স্পিকার ভলিউম সামঞ্জস্য করতে, বিল্ট-ইন setSpeakerVolumeLevel ফাংশনটি ব্যবহার করে CameraAvStreamManagementTrait ট্রেইটের speakerVolumeLevel অ্যাট্রিবিউটটি আপডেট করুন:

// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setSpeakerVolumeLevel(value)
    }
  } catch {
    // Error
  }
}

কার্যকলাপ অঞ্চলের সেটিংস

ZoneManagement ট্রেইটটি ক্যামেরা এবং ডোরবেল ডিভাইসে কাস্টম রিজিওন অফ ইন্টারেস্ট (অ্যাক্টিভিটি জোন) পরিচালনার জন্য একটি ইন্টারফেস প্রদান করে। এই জোনগুলি ডিভাইসের ফিল্ড অফ ভিউ-এর মধ্যে নির্দিষ্ট এলাকায় ইভেন্ট ডিটেকশন (যেমন ব্যক্তি বা যানবাহনের গতি) ফিল্টার করতে ব্যবহৃত হয়।

অ্যাক্টিভিটি জোনগুলি ব্যবহারকারী একটি পার্টনার অ্যাপ্লিকেশনের মধ্যে কনফিগার করেন, যা তাদের ক্যামেরার ফিল্ড অফ ভিউ-এর নির্দিষ্ট এলাকার উপর জোন আঁকতে দেয়। এই ব্যবহারকারী-সংজ্ঞায়িত জোনগুলি পরবর্তীতে এই ট্রেইট দ্বারা ব্যবহৃত স্ট্রাকচারগুলিতে রূপান্তরিত হয়। অ্যাক্টিভিটি জোনগুলি কীভাবে কাজ করে সে সম্পর্কে আরও তথ্যের জন্য, "অ্যাক্টিভিটি জোন সেট আপ এবং ব্যবহার করুন" দেখুন।

অ্যাক্টিভিটি জোন সাধারণত 2D কার্টেসিয়ান স্থানাঙ্ক ব্যবহার করে সংজ্ঞায়িত করা হয়। এই ট্রেইটটি ভার্টেক্সগুলোর জন্য TwoDCartesianVertexStruct এবং জোন সংজ্ঞার (নাম, ভার্টেক্সসমূহ, রঙ এবং ব্যবহার) জন্য TwoDCartesianZoneStruct প্রদান করে।

কার্যকলাপ অঞ্চলগুলি পরীক্ষা করুন

অ্যাক্টিভিটি জোনগুলো প্রদর্শন করতে, ZoneManagement ট্রেইটের zones অ্যাট্রিবিউটটি চেক করুন।

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
}

একটি কার্যকলাপ অঞ্চল মুছে ফেলুন

কোনো জোন অপসারণ করতে, নির্দিষ্ট zoneId সহ removeZone কমান্ডটি ব্যবহার করুন।

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 শ্রবণযোগ্য প্যাটার্ন (তিনটি ছোট বিপের পর একটি বিরতি) দ্বারা চেনা যায়।
CO অ্যালার্ম 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
)

রেকর্ডিং মোড

RecordingMode ট্রেইটটি ক্যামেরা এবং ডোরবেল ডিভাইসগুলিতে ভিডিও এবং ছবি রেকর্ডিংয়ের আচরণ পরিচালনা করার জন্য একটি ইন্টারফেস প্রদান করে। এটি ব্যবহারকারীদের অবিচ্ছিন্ন রেকর্ডিং, ইভেন্ট-ভিত্তিক রেকর্ডিং, অথবা রেকর্ডিং সম্পূর্ণরূপে নিষ্ক্রিয় করার (শুধুমাত্র লাইভ ভিউ-এর জন্য) মধ্যে যেকোনো একটি বেছে নেওয়ার সুযোগ দেয়।

RecordingModeEnum উপলব্ধ রেকর্ডিং কৌশলগুলি নির্ধারণ করে:

মোড Enum মান বর্ণনা
প্রতিবন্ধী Disabled রেকর্ডিং সম্পূর্ণরূপে নিষ্ক্রিয় করা হয়েছে। এটি মূলত পুরোনো ডিভাইসগুলোতে ব্যবহৃত হয়।
সিভিআর (ধারাবাহিক ভিডিও রেকর্ডিং) Cvr ভিডিও ২৪x৭ রেকর্ড করা হয়। এর জন্য সাবস্ক্রিপশন প্রয়োজন (যেমন, Google Google Home Premium )।
ইবিআর (ইভেন্ট ভিত্তিক রেকর্ডিং) 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)
}

অন্যান্য সেটিংস

হোম এপিআই-এর মাধ্যমে আরও বিভিন্ন সেটিংস নিয়ন্ত্রণ করা যায়।

নাইট ভিশন চালু বা বন্ধ করুন

ক্যামেরার জন্য নাইট ভিশন চালু বা বন্ধ করতে, TriStateAutoEnum ব্যবহার করে বিল্ট-ইন setNightVision ফাংশনের মাধ্যমে CameraAvStreamManagementTrait ট্রেইটের nightVision অ্যাট্রিবিউটটি আপডেট করুন:

// 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-এর উজ্জ্বলতা পরিবর্তন করতে, ThreeLevelAutoEnum ব্যবহার করে বিল্ট-ইন setStatusLightBrightness ফাংশনের মাধ্যমে CameraAvStreamManagementTrait ট্রেইটের statusLightBrightness অ্যাট্রিবিউটটি আপডেট করুন:

// Set the LED brightness
func setStatusLightBrightness(
  to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setStatusLightBrightness(value)
    }
  } catch {
    // Error
  }
}

ক্যামেরা ভিউপোর্ট পরিবর্তন করুন

ক্যামেরা ভিউপোর্টটি "জুম এবং নেস্ট ক্যামেরা ভিডিও সাপোর্ট উন্নত করুন" আর্টিকেলে বর্ণিত জুম এবং ক্রপ ফিচারের মতোই।

ভিউপোর্টটি একটি ViewportStruct মধ্যে সংজ্ঞায়িত করা হয়েছে, যেটিতে চারটি মান রয়েছে, যা ভিউপোর্টের স্থানাঙ্ক হিসেবে ব্যবহৃত হয়। স্থানাঙ্কগুলো নিম্নরূপে সংজ্ঞায়িত করা হয়েছে:

(x1,y1) -- (x2,y1)
   |          |
(x1,y2) -- (x2,y2)

ViewportStruct এর মান নির্ধারণ করা একটি অ্যাপের UI এবং ক্যামেরা বাস্তবায়নের উপর নির্ভর করে। একেবারে প্রাথমিক স্তরে, ক্যামেরা ভিডিওর ভিউপোর্ট সেট করতে, বিল্ট-ইন setViewport ফাংশনটি ব্যবহার করে CameraAvStreamManagementTrait ট্রেইটের viewport অ্যাট্রিবিউটটিকে একটি ViewportStruct দিয়ে আপডেট করুন।

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 এর প্রোপার্টিগুলোতে পরিবর্তন আনার প্রয়োজন হয়, যা পরবর্তীতে একটি স্ট্রিমিং কানেকশনের ট্রান্সপোর্ট অপশনগুলোতে পাস করা হয়। সুইফটের ক্ষেত্রে, যেকোনো প্রোপার্টি আপডেট করার আগে এই স্ট্রাক্টটি জেনারেট করতে হয়।

নিম্নলিখিত সেটিং পরিবর্তনগুলির সাথে ব্যবহারের জন্য স্ট্রাক্টটি তৈরি করতে এই হেল্পার ফাংশনটি ব্যবহার করুন:

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
}

ডিভাইস জেগে ওঠার সংবেদনশীলতা সামঞ্জস্য করুন

ডিভাইসটির ওয়েক-আপ সেনসিটিভিটি ব্যবহার করা হয় ব্যাটারি সাশ্রয়ের জন্য। এটি ডিভাইসটির কার্যকলাপ শনাক্ত করার পরিসর কমিয়ে দেয় এবং সেই কার্যকলাপ শনাক্ত করার পর জেগে ওঠার সময় বাড়িয়ে দেয়।

হোম এপিআই-গুলোতে, ডিভাইসের transportOptions এর triggerOptions এর motionSensitivity প্রপার্টি ব্যবহার করে এটি সেট করা যায়। এই অপশনগুলো প্রতিটি ডিভাইসের জন্য PushAvStreamTransportTrait ট্রেইটের মধ্যে সংজ্ঞায়িত করা থাকে।

ওয়েক-আপ সেনসিটিভিটি শুধুমাত্র নিম্নলিখিত মানগুলিতে সেট করা যেতে পারে:

  • ১ = নিম্ন
  • ৫ = মাঝারি
  • ১০ = উচ্চ

আপডেট করার প্রক্রিয়াটি হলো, findTransport কমান্ড ব্যবহার করে সক্রিয় রেকর্ডিং স্ট্রিমগুলির ট্রান্সপোর্ট কনফিগারেশন খুঁজে বের করা, তারপর modifyPushTransport কমান্ড ব্যবহার করে নতুন সেনসিটিভিটি ভ্যালু দিয়ে কনফিগারেশনটি পরিবর্তন করা।

modifyPushTransport কমান্ডটি চালানোর জন্য সম্পূর্ণ TransportOptionsStruct পাস করতে হয়, তাই আপনাকে প্রথমে বর্তমান কনফিগারেশন থেকে বিদ্যমান মানগুলো কপি করতে হবে। এই কাজটি করার জন্য একটি সহায়ক ফাংশনের জন্য "Generate a 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 APIs)-এর মাধ্যমে Google Home app (GHA) এর মতোই প্রতিটি ডিভাইসের জন্য সেকেন্ডের ব্যবধানে এই দৈর্ঘ্য কনফিগার করা যায়।

  • ১০ সেকেন্ড
  • ১৫ সেকেন্ড
  • ৩০ সেকেন্ড
  • ৬০ সেকেন্ড (১ মিনিট)
  • ১২০ সেকেন্ড (২ মিনিট)
  • ১৮০ সেকেন্ড (৩ মিনিট)

হোম এপিআই-গুলোতে, ডিভাইসের transportOptions এর triggerOptions এর motionTimeControl প্রপার্টি ব্যবহার করে এটি সেট করা যায়। এই অপশনগুলো প্রতিটি ডিভাইসের জন্য PushAvStreamTransportTrait ট্রেইটের মধ্যে সংজ্ঞায়িত করা থাকে।

আপডেট করার প্রক্রিয়াটি হলো, findTransport কমান্ড ব্যবহার করে সক্রিয় রেকর্ডিং স্ট্রিমগুলির ট্রান্সপোর্ট কনফিগারেশন খুঁজে বের করা, তারপর modifyPushTransport কমান্ড ব্যবহার করে নতুন ইভেন্ট লেংথ ভ্যালু দিয়ে কনফিগারেশনটি পরিবর্তন করা।

modifyPushTransport কমান্ডটি চালানোর জন্য সম্পূর্ণ TransportOptionsStruct পাস করতে হয়, তাই আপনাকে প্রথমে বর্তমান কনফিগারেশন থেকে বিদ্যমান মানগুলো কপি করতে হবে। এই কাজটি করার জন্য একটি সহায়ক ফাংশনের জন্য "Generate a 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
  }
}

অ্যানালিটিক্স চালু বা বন্ধ করুন

প্রতিটি ডিভাইস স্বতন্ত্রভাবে গুগল হোম ক্লাউডে বিস্তারিত অ্যানালিটিক্স ডেটা পাঠানোর জন্য সম্মতি জানাতে পারে ( হোম এপিআই-এর জন্য ক্লাউড মনিটরিং দেখুন)।

কোনো ডিভাইসের জন্য অ্যানালিটিক্স চালু করতে, ExtendedGeneralDiagnosticsTrait এর analyticsEnabled প্রপার্টিটি true তে সেট করুন। আপনি যখন analyticsEnabled সেট করেন, তখন logUploadEnabled নামক আরেকটি প্রপার্টি স্বয়ংক্রিয়ভাবে true তে সেট হয়ে যায়, যা অ্যানালিটিক্স লগ ফাইলগুলোকে গুগল হোম ক্লাউডে আপলোড করার সুযোগ দেয়।

// Enable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
  $0.setAnalyticsEnabled(true)
}

// Disable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
  $0.setAnalyticsEnabled(false)
}

ঘণ্টার শব্দ সেটিংস

হোম এপিআই-এর মাধ্যমে ডোরবেল চিমের বিভিন্ন সেটিংস নিয়ন্ত্রণ করা যায়।

ঘণ্টার ধ্বনি পরিবর্তন করুন

ডোরবেলের চিম সাউন্ড পরিবর্তন করতে, প্রথমে ChimeTrait ট্রেইটের installedChimeSounds অ্যাট্রিবিউট ব্যবহার করে ডিভাইসটিতে ইনস্টল করা চিম সাউন্ডগুলির তালিকা নিন:

doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
  return chimeSound.chimeID, chimeSound.name
}

তারপর, বিল্ট-ইন setSelectedChime ফাংশনটি ব্যবহার করে ChimeTrait ট্রেইটের selectedChime অ্যাট্রিবিউটটি আপডেট করুন:

func setDoorbellChime(chimeID: UInt8) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setSelectedChime(chimeID)
    }
  } catch {
    // Error
  }
}

বাহ্যিক ঘণ্টা ব্যবহার করুন

ডোরবেলটি বাড়ির ভেতরে ইনস্টল করা কোনো যান্ত্রিক ঘণ্টার মতো একটি বাহ্যিক ঘণ্টা ব্যবহার করার জন্য কনফিগার করা যেতে পারে। বাহ্যিক ঘণ্টাটির সম্ভাব্য ক্ষতি এড়াতে ডোরবেল ইনস্টলেশনের সময়ই এটি কনফিগার করা উচিত।

কী ধরনের এক্সটার্নাল চাইম ইনস্টল করা আছে তা নির্দেশ করতে, বিল্ট-ইন setExternalChime ফাংশনটি ব্যবহার করে ChimeTrait ট্রেইটের externalChime অ্যাট্রিবিউটটি ExternalChimeType দ্বারা আপডেট করুন:

// Indicate the external chime is mechanical
func setExternalChime(to value: Google.ChimeTrait.ExternalChimeType) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChime(value)
    }
  } catch {
    // Error
  }
}

বাহ্যিক ঘণ্টার শব্দের সময়কাল পরিবর্তন করুন

একটি এক্সটার্নাল চাইম কতক্ষণ (সেকেন্ডে) বাজবে, তা হোম এপিআই (Home APIs)-এর মাধ্যমে কনফিগার করা যেতে পারে। যদি এক্সটার্নাল চাইমটি একটি নির্দিষ্ট সময়কাল (chime duration) সমর্থন করে, তবে একজন ব্যবহারকারী এটি কনফিগার করতে চাইতে পারেন।

এখানে নির্ধারিত মানটি বাহ্যিক চাইমটির নিজস্ব বৈশিষ্ট্য এবং এর প্রস্তাবিত শব্দকালের উপর নির্ভর করে।

এক্সটার্নাল চাইমের সময়কাল পরিবর্তন করতে, বিল্ট-ইন setExternalChimeDurationSeconds ফাংশনটি ব্যবহার করে ChimeTrait ট্রেইটের externalChimeDurationSeconds অ্যাট্রিবিউটটি আপডেট করুন:

// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChimeDuration(value)
    }
  } catch {
    // Error
  }
}

একটি চিম থিম সক্রিয় করুন

কিছু ডোরবেলে এমন সুর থাকতে পারে যা ব্যবহারকারীরা কেবল সীমিত সময়ের জন্য ব্যবহার করতে পারেন। উদাহরণস্বরূপ, ছুটির দিন উপলক্ষে নির্দিষ্ট সুর। এগুলোকে চাইম থিম বলা হয়।

কোনো ব্যবহারকারীর জন্য কোন কোন চাইম থিম উপলব্ধ আছে তা দেখতে, একটি টাইমবক্স ফিল্টার তৈরি করুন এবং ChimeThemes ট্রেইট থেকে getAvailableThemes কমান্ডের ফলাফল ফিল্টার করতে এটি ব্যবহার করুন। এটি থিমের নাম সহ উপলব্ধ থিমগুলির একটি তালিকা ফেরত দেয়।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে তালিকাটি ফিল্টার করতে হয়। একটি থিমকে সক্রিয় বলে মনে করা হয় যদি বর্তমান সময়টি তার শুরু এবং শেষের সময়ের (যথাক্রমে 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 &lt;= currentDateTime
      &amp;&amp; chimeTheme.endTimeSeconds ?? UInt64.max &gt;= currentDateTime
    {
      self.chimeThemeSettings.append(chimeTheme.name)
    }
  }
}

একবার আপনার পছন্দের থিমের নাম, যেমন Christmas , ঠিক হয়ে গেলে, আপনি ChimeThemes ChimeThemes ট্রেইটের setSelectedTimeboxedThemeName() ফাংশনটি ব্যবহার করে সেটি নির্বাচন করতে পারেন।

private func setChimeTheme(to value: String) async throws {
  _ = try await chimeThemeTrait.update {
    $0.setSelectedTimeboxedThemeName(value)
  }
}```