জটিল অটোমেশনের জন্য iOS DSL গাইড

অটোমেশন ডিএসএল ব্যবহার করে এমন সব অটোমেশন তৈরি করা যায়, যা "ডিএসএল গাইড - আইওএস-এর বেসিক অটোমেশন" -এ আলোচিত অটোমেশনগুলোর চেয়েও জটিল।

একাধিক ক্রিয়াকলাপের সাথে ক্রমিক

একাধিক ক্রিয়াকলাপের সাথে ক্রমিক

একটি অটোমেশন একাধিক কাজ করতে পারে। উদাহরণস্বরূপ, একটিমাত্র action নোডের পরিবর্তে, আপনার একাধিক action নোড থাকতে পারে, যেগুলো ক্রমানুসারে চলে:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  starter(...)
  condition {...}
  action {...}
  action {...}
  action {...}

}

একাধিক সমান্তরাল ক্রিয়াকলাপের সাথে অনুক্রমিক

একাধিক সমান্তরাল ক্রিয়াকলাপের সাথে অনুক্রমিক

যদি আপনি একটি parallel নোডে একাধিক action নোড রাখেন, তাহলে অ্যাকশনগুলো একযোগে সম্পাদিত হয়।

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  starter(...)
  condition {...}
  parallel {
    action {...}
    action {...}
    action {...}
  }

}

যদি sequential নোডের মধ্যে parallel নোডের পরে কোনো action নোড থাকে, তবে সেগুলো ততক্ষণ পর্যন্ত এক্সিকিউট হওয়ার জন্য অপেক্ষা করে যতক্ষণ না parallel নোডের ভেতরের সমস্ত নোডের এক্সিকিউশন শেষ হয়।

শর্তসাপেক্ষ সম্পাদন

ডিফল্টরূপে, একটি অটোমেশন নোডগুলিকে ক্রমানুসারে বা সমান্তরালভাবে সম্পাদন করে। যদি আপনার শর্তসাপেক্ষ ব্রাঞ্চিং লজিকের প্রয়োজন হয়—অর্থাৎ রানটাইম শর্তের উপর ভিত্তি করে বিভিন্ন অ্যাকশন বা পথ সম্পাদন করা— তবে if-then-else স্টেটমেন্ট ব্যবহার করুন, যা ifThen , elseIf , এবং orElse নামক কন্ডিশনাল কন্ট্রোল ফ্লো DSL ব্লক ব্যবহার করে তৈরি করা হয়।

যেখানে একটি সাধারণ condition নোড পুরো অটোমেশনটিকে আটকে দেয় (যদি কন্ডিশনটি false প্রমাণিত হয়, অটোমেশনটি সাথে সাথে তার কার্যকারিতা বন্ধ করে দেয়), ifThen ব্লকগুলো শাখা-প্রশাখা যুক্ত নিয়ন্ত্রণ প্রবাহকে সক্ষম করে:

  • condition নোড : এক্সপ্রেশনটি false হলে সম্পূর্ণ অটোমেশন (বা বর্তমান এক্সিকিউশন পাথ)-এর এক্সিকিউশন বন্ধ করে দেয়।
  • ifThen / elseIf / orElse : শর্তগুলো ক্রমানুসারে মূল্যায়ন করে। যদি কোনো শর্ত false হয়, তাহলে এক্সিকিউশন পরবর্তী elseIf ব্রাঞ্চে বা orElse ফলব্যাক ব্রাঞ্চে চলে যায়, অথবা কোনো শর্ত পূরণ না হলে অটোমেশনের পরবর্তী নোডগুলোতে চলতে থাকে।

একটি শর্তের উপর ভিত্তি করে কোনো কাজ সম্পাদন করুন।

ifThen ব্লকটি একটি শর্তসাপেক্ষ এক্সপ্রেশন মূল্যায়ন করে। যদি এক্সপ্রেশনটির মান true হয়, তাহলে ব্লকটির ভেতরে থাকা DSL অ্যাকশন বা নোডগুলো সম্পাদিত হয়। আর যদি এর মান false হয়, তাহলে অ্যাকশনগুলো এড়িয়ে যাওয়া হয় এবং অটোমেশনটি অনুক্রমিক প্রবাহের পরবর্তী নোডগুলোতে চলতে থাকে।

যখন আপনি অটোমেশনের পরবর্তী নোডগুলিকে ব্লক বা বন্ধ না করে শুধুমাত্র শর্তসাপেক্ষে কোনো কাজ সম্পাদন করতে চান, তখন আপনি একটি স্বতন্ত্র ifThen ব্লক ব্যবহার করতে পারেন।

// When a door opens, turn on the light only if it is off,
// and always broadcast an announcement.
typealias ContactSensorDevice = Matter.ContactSensorDeviceType
typealias BooleanStateTrait = Matter.BooleanStateTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let contactState = starter(
    contactSensor,
    ContactSensorDevice.self,
    BooleanStateTrait.self
  )
  let lightState = stateReader(
    light,
    DimmableLightDevice.self,
    OnOffTrait.self
  )
  contactState
  lightState

  condition {
    // Door opened (contact sensor open)
    contactState.stateValue.equals(false)
  }

  // Conditionally turn on the light if it's off
  ifThen(lightState.onOff.equals(false)) {
    action(light, DimmableLightDevice.self) {
      OnOffTrait.on()
    }
  }

  // Continue executing subsequent actions in the sequential flow
  action(structure) {
    Google.AssistantBroadcastTrait.broadcast(msg: "The door was opened.")
  }
}

একটি শর্তের উপর ভিত্তি করে বিভিন্ন কাজ সম্পাদন করুন।

কোনো শর্ত সত্য হলে এক সেট কাজ এবং মিথ্যা হলে অন্য সেট কাজ সম্পাদন করতে, ifThen(...) { ... } এর পরে ঐচ্ছিক .orElse { ... } ব্লকটি যুক্ত করুন:

// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLockTrait = Matter.DoorLockTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let doorLockEvent = starter(
    doorLock,
    DoorLockDevice.self,
    DoorLockTrait.LockOperationEvent.self
  )
  let lightState = stateReader(
    light,
    DimmableLightDevice.self,
    OnOffTrait.self
  )
  doorLockEvent
  lightState

  condition {
    doorLockEvent.lockOperationType.equals(.unlock)
  }

  ifThen(lightState.onOff.equals(false)) {
    action(light, DimmableLightDevice.self) {
      OnOffTrait.on()
    }
  }.orElse {
    action(structure) {
      Google.AssistantBroadcastTrait.broadcast(msg: "Welcome home!")
    }
  }
}

একাধিক শর্ত ক্রমানুসারে সাজান।

আপনি ক্রমানুসারে একাধিক শর্ত মূল্যায়ন করতে এক বা একাধিক ঐচ্ছিক .elseIf(...) { ... } ব্লক যুক্ত করতে পারেন। যে শাখার শর্তটি প্রথমে true বলে প্রমাণিত হয়, সেটিই কার্যকর হয় এবং বাকি সমস্ত শাখা এড়িয়ে যাওয়া হয়। যদি কোনো শর্তই true বলে প্রমাণিত না হয়, তাহলে একটি ঐচ্ছিক .orElse { ... } ব্লক কার্যকর হয় (যদি প্রদান করা হয়):

// Adjust climate controls based on room temperature changes.
typealias TemperatureSensorDeviceType = Matter.TemperatureSensorDeviceType
typealias TemperatureMeasurementTrait = Matter.TemperatureMeasurementTrait
typealias ThermostatDeviceType = Matter.ThermostatDeviceType
typealias SimplifiedThermostatTrait = Google.SimplifiedThermostatTrait
typealias FanDeviceType = Matter.FanDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let tempStarter = starter(
    tempSensor,
    TemperatureSensorDeviceType.self,
    TemperatureMeasurementTrait.self
  )
  tempStarter

  // If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
  ifThen(tempStarter.measuredValue.greaterThanOrEquals(2800)) {
    action(thermostat, ThermostatDeviceType.self) {
      SimplifiedThermostatTrait.setSystemMode(systemMode: .cool)
    }
  }.elseIf(tempStarter.measuredValue.lessThan(1800)) {
    // If temperature is low (< 18°C / 1800 mC), switch to Heat mode
    action(thermostat, ThermostatDeviceType.self) {
      SimplifiedThermostatTrait.setSystemMode(systemMode: .heat)
    }
  }.orElse {
    // Otherwise, turn on the fan
    action(fan, FanDeviceType.self) {
      OnOffTrait.on()
    }
  }
}

নেস্টেড কন্ডিশনাল ফ্লো

কন্ডিশনাল ব্লকগুলোকে অন্যান্য ifThen , elseIf , বা orElse ব্লকের ভিতরে নেস্ট করা যায়, এবং সেইসাথে parallel , delay(for:) , ও stateReader নোডগুলোর সাথেও একত্রিত করা যায়।

ifThen , elseIf , এবং orElse ব্লকগুলো তাদের ভেতরের বিষয়বস্তু ক্রমানুসারে সম্পাদন করে। আপনি প্রতিটি শাখার ভেতরে যেকোনো ক্রমানুসারে সাজানো নোড রাখতে পারেন, যার মধ্যে action , stateReader , parallel , delay(for:) , এবং নেস্টেড ifThen ব্লকও অন্তর্ভুক্ত।

বিলম্ব

আপনি delay(for:) মেথড ব্যবহার করে আপনার অটোমেশনে বিরতি যোগ করতে পারেন। এই মেথডটি একটি Duration আর্গুমেন্ট গ্রহণ করে, যা নির্দেশ করে যে এক্সিকিউশন চালিয়ে যাওয়ার আগে কতক্ষণ বিরতি নিতে হবে। বিরতির সময়কাল সর্বনিম্ন পাঁচ সেকেন্ড থেকে সর্বোচ্চ ২৪ ঘণ্টা পর্যন্ত হতে পারে।

উদাহরণস্বরূপ, প্রতিটি টগলের মধ্যে পাঁচ সেকেন্ডের বিরতি দিয়ে একটি আলো চারবার টগল করতে:

typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

sequential {
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}

ট্রিগার দমন

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

আপনার অটোমেশনে ট্রিগার সাপ্রেশন প্রয়োগ করতে, suppress(for:) কীওয়ার্ডটি ব্যবহার করুন এবং এর সাথে ` Duration আর্গুমেন্টটি যুক্ত করুন, যা নির্দেশ করে পরবর্তী ট্রিগারগুলিতে সাড়া দেওয়ার আগে কতক্ষণ অপেক্ষা করতে হবে। সাপ্রেশনের সময়কাল সর্বনিম্ন পাঁচ সেকেন্ড থেকে সর্বোচ্চ ২৪ ঘণ্টা পর্যন্ত হতে পারে।

typealias OccupancySensorDevice = Matter.OccupancySensorDeviceType
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias MotionDetectionTrait = Google.MotionDetectionTrait
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let starterNode = starter(device, OccupancySensorDevice.self, MotionDetectionTrait.self)
  starterNode
  suppress(for: .seconds(30 * 60)) // 30 minutes
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}

মনে রাখবেন যে ট্রিগার সাপ্রেশন একটি অটোমেশনের মধ্যে থাকা সেই সমস্ত starters প্রভাবিত করে যা Suppression আগে থাকে।

মৃত্যুদণ্ডের সংখ্যা সীমিত করুন

একটি অটোমেশন কতবার চালানো যাবে তা আপনি সীমিত করতে পারেন।

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

এটি করার জন্য, অটোমেশনটির maxExecutionCount মেটাডেটা ফিল্ডটি সেট করুন। নিচের উদাহরণটি এমন একটি অটোমেশন যা শুধুমাত্র একবারই এক্সিকিউট হতে পারে:

import GoogleHomeSDK
import GoogleHomeTypes

typealias RoboticVacuumCleanerDevice = Matter.RoboticVacuumCleanerDeviceType
typealias RvcRunModeTrait = Matter.RvcRunModeTrait
typealias AreaPresenceStateTrait = Google.AreaPresenceStateTrait

let draftAutomation = automation(
  name: "Vacuum home away",
  description: "Run the vacuum once when everyone is away.",
  maxExecutionCount: 1
) {
  let homeAwayState = starter(structure, AreaPresenceStateTrait.self)
  homeAwayState

  condition {
    homeAwayState.presenceState.equals(.presenceStateVacant)
  }

  action(vacuum, RoboticVacuumCleanerDevice.self) {
    RvcRunModeTrait.changeToMode(newMode: 1)
  }
}

অটোমেশনটি শেষবারের মতো কার্যকর হওয়া শেষ হলে এবং maxExecutionCount পৌঁছালে তা সঙ্গে সঙ্গে মুছে ফেলা হয়। অটোমেশনটির হিস্ট্রি এন্ট্রি, automation_id সহ, Google Home app (GHA) অ্যাক্টিভিটি ট্যাবে থেকে যায়।

একটি অ্যাকশনে বৈশিষ্ট্যের অ্যাট্রিবিউট সেট করুন

একটি ট্রেইট অ্যাট্রিবিউটের মান নির্ধারণ করতে:

  1. একটি action নোডের মধ্যে একটি update নোড তৈরি করুন এবং update নোডটির আর্গুমেন্ট হিসেবে প্রাসঙ্গিক ট্রেইটটি অন্তর্ভুক্ত করুন:
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
    
  2. update নোডের মধ্যে, পরিবর্তন করতে হবে এমন প্রতিটি অ্যাট্রিবিউটের জন্য একটি মিউটেটর ফাংশন ব্যবহার করুন এবং এতে নতুন মানটি পাস করুন। মিউটেটর ফাংশনটির নাম তৈরি করতে:
    1. অ্যাট্রিবিউটের নামটি বড় হাতের অক্ষরে লিখুন।
    2. এর আগে ' set শব্দটি যুক্ত করুন।
    উদাহরণস্বরূপ, defaultMoveRate নামক একটি অ্যাট্রিবিউট আপডেট করতে, আপনাকে setDefaultMoveRate নামক একটি মিউটেটর ফাংশন ব্যবহার করতে হবে।

মনে রাখবেন যে একটি update নোডে একাধিক মিউটেটর ফাংশন থাকতে পারে। এখানে একটি উদাহরণ দেওয়া হলো যেখানে দুটি অ্যাট্রিবিউট আপডেট করা হয়েছে:

typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait

action(fan, FanDeviceType.self) {
  update(FanControlTrait.self) {
    $0.setFanMode(.on)
  }
}