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

অটোমেশন DSL ব্যবহার করে এমন অটোমেশন তৈরি করা যায় যা DSL গাইড - Android-এ প্রাথমিক অটোমেশন লিঙ্কে আলোচনা করা অটোমেশনের চেয়ে অনেক বেশি জটিল।

একাধিক অ্যাকশন সহ সিকোয়েন্সিয়াল

একাধিক অ্যাকশন সহ সিকোয়েন্সিয়াল

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

automation {
  sequential {
    starter<_>(...)
    condition {...}
    action {...}
    action {...}
    action {...}
    }
}

একাধিক প্যারালাল অ্যাকশন সহ সিকোয়েন্সিয়াল

একাধিক প্যারালাল অ্যাকশন সহ সিকোয়েন্সিয়াল

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

automation {
  sequential {
    starter<_>(...)
    condition {...}
    parallel {
      action {...}
      action {...}
      action {...}
    }
  }
}

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

শর্তসাপেক্ষ এক্সিকিউশন

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

স্ট্যান্ডার্ড 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.
automation {
  sequential {
    val contactState = starter<_>(
      contactSensor,
      ContactSensorDevice,
      BooleanState,
    )
    val lightState = stateReader<_>(
      light,
      DimmableLightDevice,
      OnOff,
    )

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

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

    // Continue executing subsequent actions in the sequential flow
    action(structure) {
      command(AssistantBroadcast.broadcast("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.
automation {
  sequential {
    val doorLockEvent = starter<_>(
      doorLock,
      DoorLockDevice,
      LockOperationEvent,
    )
    val lightState = stateReader<_>(
      light,
      DimmableLightDevice,
      OnOff,
    )

    condition {
      expression =
        doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
    }

    ifThen(lightState.onOff equals false) {
      action(light, DimmableLightDevice) { command(OnOff.on()) }
    }.orElse {
      action(structure) {
        command(AssistantBroadcast.broadcast("Welcome home!"))
      }
    }
  }
}

পরপর একাধিক শর্ত যোগ করা

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

// Adjust climate controls based on room temperature changes.
automation {
  sequential {
    val tempStarter = starter<_>(
      tempSensor,
      TemperatureSensorDevice,
      TemperatureMeasurement,
    )

    // If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
    ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
      action(thermostat, ThermostatDevice) {
        command(
          SimplifiedThermostat.setSystemMode(
            SimplifiedThermostatSystemModeEnum.Cool
          )
        )
      }
    }.elseIf(tempStarter.measuredValue lessThan 1800) {
      // If temperature is low (< 18°C / 1800 mC), switch to Heat mode
      action(thermostat, ThermostatDevice) {
        command(
          SimplifiedThermostat.setSystemMode(
            SimplifiedThermostatSystemModeEnum.Heat
          )
        )
      }
    }.orElse {
      // Otherwise, turn on the fan
      action(fan, FanDevice) {
        command(OnOff.on())
      }
    }
  }
}

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

কন্ডিশনাল ব্লক অন্য ifThen, elseIf বা orElse ব্লকের মধ্যে নেস্ট করা যেতে পারে, সেইসাথে parallel, delayFor, ও stateReader নোডের সাথেও একত্রিত করা যেতে পারে।

ifThen, elseIf ও orElse ব্লকগুলি তাদের কন্টেন্টকে সিকোয়েন্সিয়াল ফ্লো হিসেবে এক্সিকিউট করে। আপনি প্রতিটি শাখার মধ্যে যেকোনও ক্রমিক নোড প্লেস করতে পারবেন, যার মধ্যে action, stateReader, parallel, delayFor এবং নেস্ট করা ifThen ব্লক অন্তর্ভুক্ত।

দেরি

আপনি delayFor কীওয়ার্ড ব্যবহার করে অটোমেশনে পজ যোগ করতে পারবেন, এটি একটি java.time.Duration আর্গুমেন্ট নেয় যা এক্সিকিউশন চালিয়ে যাওয়ার আগে কতক্ষণ পজ করতে হবে তা বোঝায়। পজ করার সময়সীমা পাঁচ সেকেন্ড থেকে ২৪ ঘণ্টা পর্যন্ত হতে পারে।

যেমন, প্রতিটি টগল করার মধ্যে পাঁচ সেকেন্ডের বিরতি সহ কোনও লাইট চারবার টগল করতে:

sequential {
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}

ট্রিগার আটকানো

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

আপনার অটোমেশনে ট্রিগার সাপ্রেশন প্রয়োগ করতে, suppressFor কীওয়ার্ডের সাথে java.time.Duration আর্গুমেন্ট ব্যবহার করুন। এই আর্গুমেন্টটি পরবর্তী ট্রিগারকে উত্তর দেওয়ার আগে কতক্ষণ অপেক্ষা করতে হবে তা দেখায়। সাপপ্রেস করার সময়সীমা পাঁচ সেকেন্ড থেকে ২৪ ঘণ্টা পর্যন্ত হতে পারে।

automation {
  sequential {
    val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
    suppressFor(Duration.ofMinutes(30))
    action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}

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

এক্সিকিউশনের সংখ্যা সীমিত করা

কোনও অটোমেশন কতবার চালানোর অনুমতি দেওয়া হবে তা আপনি সীমিত করতে পারবেন।

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

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

automation {
  // The automation can only be executed once.
  maxExecutionCount = 1
  // When the door lock state changes
  sequential {
    val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent)
    // if the door is unlocked
    condition() {
      expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock)
    }
    // turn the light on
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}

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

অ্যাকশনে ট্রেট অ্যাট্রিবিউট সেট করা

কোনও ট্রেট অ্যাট্রিবিউটের ভ্যালু সেট করতে:

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

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

action(device, Fan) {
  update(FanControl) {
    setPercentSetting(50u)
    setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
  }
}