জটিল অটোমেশনের জন্য অ্যান্ড্রয়েড ডিএসএল গাইড

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

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

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

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

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

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

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

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

automation {
  sequential {
    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.
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()) }
}

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

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

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

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

এটি করার জন্য, অটোমেশনটির 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 পৌঁছালে তা সঙ্গে সঙ্গে মুছে ফেলা হয়। অটোমেশনটির হিস্ট্রি এন্ট্রি, automation_id সহ, Google Home app (GHA) অ্যাক্টিভিটি ট্যাবে থেকে যায়।

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

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

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