คู่มือ DSL ของ Android สําหรับการทำงานอัตโนมัติที่ซับซ้อน

คุณสามารถใช้ Automation DSL เพื่อสร้างการทำงานอัตโนมัติที่ซับซ้อนกว่า ที่กล่าวถึงใน คู่มือ DSL - การทำงานอัตโนมัติพื้นฐานใน Android

การทำงานตามลำดับที่มีการดำเนินการหลายอย่าง

ตามลำดับที่มีการดำเนินการหลายอย่าง

การทำงานอัตโนมัติสามารถทำได้มากกว่า 1 อย่าง เช่น คุณสามารถมีโหนด action หลายโหนดแทนโหนด action โหนดเดียว ซึ่งจะทำงานตามลำดับ

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

การทำงานตามลำดับที่มีการดำเนินการแบบขนานหลายอย่าง

ตามลำดับที่มีการดำเนินการแบบขนานหลายรายการ

หากคุณวางโหนด action หลายโหนดไว้ในโหนด parallel การดำเนินการจะทำงานพร้อมกัน

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

หากมีโหนด action ในโหนด sequential ที่อยู่หลังโหนด 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."))
    }
  }
}

ดำเนินการต่างๆ ตามเงื่อนไข

หากต้องการดำเนินการชุดการดำเนินการหนึ่งเมื่อเงื่อนไขเป็นจริง และดำเนินการชุดการดำเนินการอื่นเมื่อเงื่อนไขเป็นเท็จ ให้เชื่อมบล็อก .orElse { ... } ที่ไม่บังคับไว้หลังบล็อก ifThen(...) { ... }

// 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(...) { ... } ที่ไม่บังคับอย่างน้อย 1 บล็อกเพื่อประเมินเงื่อนไขหลายรายการตามลำดับ ระบบจะดำเนินการสาขาแรกที่เงื่อนไขประเมินเป็น 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 ที่แสดงระยะเวลาที่จะหยุดชั่วคราวก่อนดำเนินการต่อ ระยะเวลาหยุดชั่วคราวอาจสั้นเพียง 5 วินาทีหรือนานถึง 24 ชั่วโมง

ตัวอย่างเช่น หากต้องการสลับไฟ 4 ครั้งโดยหยุดชั่วคราว 5 วินาทีระหว่างการสลับแต่ละครั้ง ให้ทำดังนี้

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 ที่ทริกเกอร์โดยการตรวจจับการเคลื่อนไหว และหากคุณระบุระยะเวลาระงับทริกเกอร์เป็น 5 นาที เมื่อ starter ทริกเกอร์แล้ว จะไม่ทริกเกอร์อีกครั้งในอีก 5 นาทีข้างหน้า ซึ่งจะป้องกันไม่ให้การทำงานอัตโนมัติทริกเกอร์ซ้ำๆ อย่างรวดเร็ว

หากต้องการใช้การระงับทริกเกอร์กับการทำงานอัตโนมัติ ให้ใช้คีย์เวิร์ด suppressFor กับ java.time.Duration อาร์กิวเมนต์ที่แสดงระยะเวลาที่จะรอการตอบสนองต่อทริกเกอร์ที่ตามมา ระยะเวลาระงับอาจสั้นเพียง 5 วินาทีหรือนานถึง 24 ชั่วโมง

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. สร้างโหนด update ภายในโหนด action โดยรวมลักษณะที่เกี่ยวข้องเป็นอาร์กิวเมนต์ของโหนด update ดังนี้
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
  2. ภายในโหนด update ให้ใช้ฟังก์ชัน Mutator สำหรับแต่ละแอตทริบิวต์ที่จะแก้ไข และส่งค่าใหม่ไปยังฟังก์ชันดังกล่าว วิธีสร้างชื่อฟังก์ชัน Mutator
    1. ขึ้นต้นชื่อแอตทริบิวต์ด้วยตัวพิมพ์ใหญ่
    2. นำหน้าด้วยคำว่า set
    ตัวอย่างเช่น หากต้องการอัปเดตแอตทริบิวต์ที่ชื่อว่า defaultMoveRate, คุณจะต้องใช้ฟังก์ชัน Mutator ที่ชื่อว่า setDefaultMoveRate.

โปรดทราบว่าโหนด update มีฟังก์ชัน Mutator ได้หลายฟังก์ชัน ตัวอย่างต่อไปนี้แสดงการอัปเดตแอตทริบิวต์ 2 รายการ

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