Bạn có thể truy cập vào Automation API thông qua Home API cho Android, nhưng vì điểm truy cập của các API này là thông qua một cấu trúc, nên trước tiên, bạn phải cấp quyền trên cấu trúc thì mới có thể sử dụng các API này.
Sau khi cấp quyền cho một cấu trúc, hãy nhập các gói này vào ứng dụng:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
import com.google.home.Structure
Một cấu trúc chứa
HasAutomations
giao diện với các phương thức dành riêng cho quy trình tự động hoá sau:
| API | Mô tả |
|---|---|
automations() |
Liệt kê tất cả các quy trình tự động hoá thuộc cấu trúc. Hệ thống chỉ trả về các quy trình tự động hoá mà bạn đã tạo thông qua Home API. |
createAutomation(automation) |
Tạo một thực thể quy trình tự động hoá cho một cấu trúc. |
deleteAutomation(automationId) |
Xoá một thực thể quy trình tự động hoá theo mã nhận dạng. |
Tạo một quy trình tự động hoá
Sau khi tạo một thực thể của Home và nhận được quyền từ người dùng, hãy lấy cấu trúc và(các) thiết bị:
val structure = homeManager.structures().list().single()
val device = homeManager.devices().get(Id("myDevice"))!!
Sau đó, hãy xác định logic của quy trình tự động hoá bằng Automation DSL. Trong Home API, một quy trình tự động hoá được biểu thị bằng giao diện Automation. Giao diện này chứa một tập hợp các thuộc tính:
- Siêu dữ liệu, chẳng hạn như tên và nội dung mô tả.
- Các cờ cho biết, ví dụ: liệu có thể thực thi quy trình tự động hoá hay không.
- Một danh sách các nút chứa logic của quy trình tự động hoá, được gọi là biểu đồ quy trình tự động hoá, được biểu thị bằng thuộc tính
automationGraph.
Theo mặc định, automationGraph thuộc loại SequentialFlow, là một lớp chứa danh sách các nút thực thi theo thứ tự tuần tự. Mỗi nút đại diện cho một phần tử của quy trình tự động hoá, chẳng hạn như điều kiện khởi động, điều kiện hoặc hành động.
Chỉ định name và description cho quy trình tự động hoá.
Việc tạo một quy trình tự động hoá sẽ đặt cờ isActive thành true. Do đó, bạn không cần phải đặt cờ này một cách rõ ràng, trừ phi bạn muốn tắt quy trình tự động hoá ngay từ đầu. Trong trường hợp đó, hãy đặt cờ thành false trong quá trình tạo.
Giao diện DraftAutomation dùng để xây dựng và tạo quy trình tự động hoá,
còn giao diện Automation dùng để truy xuất. Ví dụ: đây là Automation DSL cho một quy trình tự động hoá bật một thiết bị khi một thiết bị khác được bật:
import com.google.home.automation.Action
import com.google.home.automation.Automation
import com.google.home.automation.Condition
import com.google.home.automation.DraftAutomation
import com.google.home.automation.Equals
import com.google.home.automation.Node
import com.google.home.automation.SequentialFlow
import com.google.home.automation.Starter
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.matter.standard.OnOff
import com.google.home.Structure
...
val automation: DraftAutomation = automation {
name = "MyFirstAutomation"
description = "Turn on a device when another device is turned on."
sequential {
val starterNode = starter<_>(device1, OnOffLightDevice, trait=OnOff)
condition() { expression = stateReaderNode.onOff equals true }
action(device2, OnOffLightDevice) { command(OnOff.on()) }
}
}
Sau khi xác định Automation DSL, hãy truyền DSL này đến
createAutomation()
phương thức để tạo thực thể DraftAutomation:
val createdAutomation = structure.createAutomation(automation)
Từ đây, bạn có thể sử dụng tất cả các phương thức tự động hoá khác trên quy trình tự động hoá, chẳng hạn như execute(), stop() và update().
Lỗi xác thực
Nếu quá trình tạo quy trình tự động hoá không vượt qua quy trình xác thực, thì thông báo cảnh báo hoặc thông báo lỗi sẽ cung cấp thông tin về vấn đề. Để biết thêm thông tin, hãy tham khảo tài liệu tham khảo
ValidationIssueType.
Ví dụ về mã
Sau đây là một số ví dụ về mã có thể dùng để triển khai các phần của quy trình tự động hoá giả định được mô tả trên trang Thiết kế quy trình tự động hoá trên Android.
Quy trình tự động hoá đơn giản
Một quy trình tự động hoá nâng rèm cửa lúc 8:00 sáng có thể được triển khai như sau:
// get all the automation node candidates in the structure
val allCandidates = structure.allCandidates().first()
// determine whether a scheduled automation can be constructed
val isSchedulingSupported =
allCandidates.any {
it is EventCandidate &&
it.eventFactory == Time.ScheduledTimeEvent &&
it.unsupportedReasons.isEmpty()
}
// get the blinds present in the structure
val blinds =
allCandidates
.filter {
it is CommandCandidate &&
it.commandDescriptor == WindowCoveringTrait.UpOrOpenCommand &&
it.unsupportedReasons.isEmpty()
}
.map { it.entity }
.filterIsInstance<HomeDevice>()
.filter { it.has(WindowCoveringDevice) }
if (isSchedulingSupported && blinds.isNotEmpty()) {
// Proceed to create automation
val automation: DraftAutomation = automation {
name = "Day time open blinds"
description = "Open all blinds at 8AM everyday"
isActive = true
sequential {
// At 8:00am local time....
val unused =
starter(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(LocalTime.of(8, 0, 0, 0)))
}
// ...open all the blinds
parallel {
for (blind in blinds) {
action(blind, WindowCoveringDevice) { command(WindowCovering.upOrOpen()) }
}
}
}
}
val createdAutomation = structure.createAutomation(automation)
} else if (!isSchedulingSupported) {
// Cannot create automation.
// Set up your address on the structure, then try again.
} else {
// You don't have any WindowCoveringDevices.
// Try again after adding some blinds to your structure.
}
Quy trình tự động hoá phức tạp
import com.google.home.Home
import com.google.home.HomeClient
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.equals
import com.google.home.automation.parallel
import com.google.home.automation.starter
import com.google.home.google.AssistantBroadcast
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOff.Companion.toggle
import com.google.home.matter.standard.OnOffLightDevice
import java.time.Duration
// get all the automation node candidates in the structure
val allCandidates = structure.allCandidates().first()
// get the lights present in the structure
val availableLights = allCandidates.filter {
it is CommandCandidate &&
it.commandDescriptor == OnOffTrait.OnCommand
}.map { it.entity }
.filterIsInstance<HomeDevice>()
.filter {it.has(OnOffLightDevice) ||
it.has(ColorTemperatureLightDevice) ||
it.has(DimmableLightDevice) ||
it.has(ExtendedColorLightDevice)}
val selectedLights = ... // user selects one or more lights from availableLights
automation {
isActive = true
sequential {
// If the presence state changes...
val starterNode = starter<_>(structure, AreaPresenceState)
// ...and if the area is occupied...
condition() {
expression = starterNode.presenceState equals PresenceState.PresenceStateOccupied
}
// "blink" the light(s)
parallel {
for(light in selectedLights) {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle())}
}
}
}
}
Chọn thiết bị một cách linh hoạt bằng bộ lọc thực thể
Khi viết một quy trình tự động hoá, bạn không bị giới hạn trong việc chỉ định các thiết bị cụ thể. Một tính năng có tên là bộ lọc thực thể cho phép quy trình tự động hoá chọn thiết bị trong thời gian chạy dựa trên nhiều tiêu chí.
Ví dụ: bằng cách sử dụng bộ lọc thực thể, quy trình tự động hoá có thể nhắm đến:
- tất cả các thiết bị thuộc một loại thiết bị cụ thể
- tất cả các thiết bị trong một phòng cụ thể
- tất cả các thiết bị thuộc một loại thiết bị cụ thể trong một phòng cụ thể
- tất cả các thiết bị đang bật
- tất cả các thiết bị đang bật trong một phòng cụ thể
Cách sử dụng bộ lọc thực thể:
- Trên
StructurehoặcRoom, hãy gọiatExecutionTime(). Thao tác này sẽ trả vềTypedExpression<TypedEntity<StructureType>>. - Trên đối tượng này, hãy gọi
getDevicesOfType(), truyền đối tượng này vàoDeviceType.
Bạn có thể sử dụng bộ lọc thực thể trong điều kiện khởi động, trình đọc trạng thái và hành động.
Ví dụ: để bất kỳ Đèn bật/tắt nào kích hoạt một quy trình tự động hoá từ điều kiện khởi động:
// If any light is turned on or off val starter = starter( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Để nắm bắt trạng thái OnOff của tất cả các đèn trong một cấu trúc (cụ thể là đèn bật/tắt) trong trình đọc trạng thái:
// Build a Map<Entity, OnOff> val onOffStateOfAllLights = stateReader( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Để lấy đèn trong một phòng cụ thể và sử dụng đèn đó trong một điều kiện:
val livingRoomLights = stateReader( entityExpression = livingRoom.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, ) // Are any of the lights in the living room on? condition { expression = livingRoomLights.values.any { it.onOff equals true } }
Trong thời gian chạy:
| Trường hợp | Kết quả |
|---|---|
| Không có thiết bị nào đáp ứng tiêu chí trong điều kiện khởi động. | Quy trình tự động hoá không kích hoạt. |
| Không có thiết bị nào đáp ứng tiêu chí trong trình đọc trạng thái. | Quy trình tự động hoá bắt đầu nhưng sẽ tiếp tục dựa trên nút điều kiện. |
| Không có thiết bị nào đáp ứng tiêu chí trong một hành động. | Quy trình tự động hoá bắt đầu nhưng hành động không thực hiện bất kỳ thao tác nào. |
Ví dụ sau đây là một quy trình tự động hoá tắt tất cả các đèn, ngoại trừ đèn hành lang bất cứ khi nào một đèn riêng lẻ bị tắt:
val unused = automation { sequential { // If any light is turned on or off val starter = starter( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, ) condition { // Check to see if the triggering light was turned off expression = starter.onOff equals false } // Turn off all lights except the hall light action( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice).filter { it notEquals entity(hallwayLight, OnOffLightDevice) } ) { command(OnOff.on()) } } }
Thực thi một quy trình tự động hoá
Chạy một quy trình tự động hoá đã tạo bằng phương thức
execute():
createdAutomation.execute()
Nếu quy trình tự động hoá có điều kiện khởi động thủ công, thì execute()
sẽ bắt đầu quy trình tự động hoá từ điểm đó, bỏ qua tất cả các nút đứng trước điều kiện khởi động thủ công. Nếu quy trình tự động hoá không có điều kiện khởi động thủ công, thì quá trình thực thi sẽ bắt đầu từ nút sau nút điều kiện khởi động đầu tiên.
Nếu thao tác execute() không thành công, thì HomeException có thể được gửi. Xem phần Xử lý
lỗi.
Dừng một quy trình tự động hoá
Dừng một quy trình tự động hoá đang chạy bằng phương thức stop():
createdAutomation.stop()
Nếu thao tác stop() không thành công, thì HomeException có thể được gửi. Xem phần Xử lý
lỗi.
Xem danh sách các quy trình tự động hoá cho một cấu trúc
Các quy trình tự động hoá được xác định ở cấp cấu trúc. Thu thập trên cấu trúc's
automations()
để truy cập vào Flow của các quy trình tự động hoá:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
structure.automations().collect {
println("Available automations:")
for (automation in it) {
println(String.format("%S %S", "$automation.id", "$automation.name"))
}
}
Ngoài ra, hãy chỉ định quy trình tự động hoá cho một Collection cục bộ:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
var myAutomations: Collection<Automation> = emptyList()
myAutomations = structure.automations()
Xem một quy trình tự động hoá theo mã nhận dạng
Để xem một quy trình tự động hoá theo mã nhận dạng quy trình tự động hoá, hãy gọi
automations()
phương thức trên cấu trúc và so khớp theo mã nhận dạng:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
Phản hồi:
// Here's how the automation looks like in the get response.
// Here, it's represented as if calling a println(automation.toString())
Automation(
name = "automation-name",
description = "automation-description",
isActive = true,
id = Id("automation@automation-id"),
automationGraph = SequentialFlow(
nodes = [
Starter(
entity="device@test-device",
type="home.matter.0000.types.0101",
trait="OnOff@6789..."),
Action(
entity="device@test-device",
type="home.matter.0000.types.0101",
trait="OnOff@8765...",
command="on")
]))
Xem một quy trình tự động hoá theo tên
Bạn có thể sử dụng phương thức
filter()
trong Kotlin để tinh chỉnh thêm các lệnh gọi API. Để xem một quy trình tự động hoá theo tên, hãy xem các quy trình tự động hoá của cấu trúc và lọc theo tên quy trình tự động hoá:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().filter {
it.name.equals("Sunset Blinds") }
Xem tất cả các quy trình tự động hoá cho một thiết bị
Để xem tất cả các quy trình tự động hoá tham chiếu đến một thiết bị nhất định, hãy sử dụng tính năng lọc lồng nhau để quét automationGraph của từng quy trình tự động hoá:
import android.util.Log
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
import com.google.home.automation.Action
import com.google.home.automation.Automation
import com.google.home.automation.Automation.automationGraph
import com.google.home.automation.Node
import com.google.home.automation.ParallelFlow
import com.google.home.automation.SelectFlow
import com.google.home.automation.SequentialFlow
import com.google.home.automation.Starter
import com.google.home.automation.StateReader
...
fun collectDescendants(node: Node): List<Node> {
val d: MutableList<Node> = mutableListOf(node)
val children: List<Node> =
when (node) {
is SequentialFlow -> node.nodes
is ParallelFlow -> node.nodes
is SelectFlow -> node.nodes
else -> emptyList()
}
for (c in children) {
d += collectDescendants(c)
}
return d
}
val myDeviceId = "device@452f78ce8-0143-84a-7e32-1d99ab54c83a"
val structure = homeManager.structures().list().single()
val automations =
structure.automations().first().filter {
automation: Automation ->
collectDescendants(automation.automationGraph!!).any { node: Node ->
when (node) {
is Starter -> node.entity.id.id == myDeviceId
is StateReader -> node.entity.id.id == myDeviceId
is Action -> node.entity.id.id == myDeviceId
else -> false
}
}
}
Cập nhật một quy trình tự động hoá
Để cập nhật siêu dữ liệu của một quy trình tự động hoá, hãy gọi phương thức
update()
của quy trình tự động hoá đó, truyền phương thức này vào một biểu thức lambda đặt siêu dữ liệu:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
automation.update { this.name = "Flashing lights 2" }
Phương thức update()
hỗ trợ thay thế hoàn toàn biểu đồ quy trình tự động hoá, nhưng không hỗ trợ chỉnh sửa từng nút của
biểu đồ. Việc chỉnh sửa từng nút dễ gây ra lỗi do sự phụ thuộc lẫn nhau giữa các nút. Nếu bạn muốn thay đổi logic của một quy trình tự động hoá, hãy tạo một biểu đồ mới và thay thế hoàn toàn biểu đồ hiện có.
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: Automation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
automation.update {
this.automationGraph = sequential {
val laundryWasherCompletionEvent =
starter<_>(laundryWasher, LaundryWasherDevice, OperationCompletionEvent)
condition {
expression =
laundryWasherCompletionEvent.completionErrorCode equals
// UByte 0x00u means NoError
0x00u
}
action(speaker, SpeakerDevice) { command(AssistantBroadcast.broadcast("laundry is done")) }
}
}
}
Xoá quy trình tự động hoá
Để xoá một quy trình tự động hoá, hãy sử dụng phương thức
deleteAutomation()
của cấu trúc. Bạn phải xoá một quy trình tự động hoá bằng mã nhận dạng của quy trình đó.
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().first()
structure.deleteAutomation(automation.id)
Nếu quá trình xoá không thành công, thì HomeException có thể được gửi. Xem phần Xử lý
lỗi.
Tác động của việc xoá thiết bị đối với quy trình tự động hoá
Nếu người dùng xoá một thiết bị được sử dụng trong một quy trình tự động hoá, thì thiết bị đã xoá không thể kích hoạt bất kỳ điều kiện khởi động nào và quy trình tự động hoá sẽ không thể đọc các thuộc tính từ thiết bị đó hoặc gửi lệnh đến thiết bị đó. Ví dụ: nếu người dùng xoá
OccupancySensorDevice
khỏi nhà và một quy trình tự động hoá có điều kiện khởi động phụ thuộc vào
the OccupancySensorDevice, thì điều kiện khởi động đó không còn có thể kích hoạt quy trình tự động hoá.