يمكن الوصول إلى واجهات برمجة التطبيقات Automation API من خلال واجهات برمجة التطبيقات Home API لنظام التشغيل Android، ولكن بما أنّ نقطة دخولها هي من خلال بنية، يجب أولاً منح الإذن بالبنية قبل استخدامها.
بعد منح الأذونات لبنية معيّنة، استورِد الحِزم التالية إلى تطبيقك:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
import com.google.home.Structure
تحتوي البنية على واجهة
HasAutomations
تتضمّن الطرق التالية المتعلّقة بالتشغيل الآلي:
واجهة برمجة التطبيقات | الوصف |
---|---|
automations() |
إدراج جميع عمليات التشغيل الآلي التي تنتمي إلى البنية لا يتم عرض سوى الإجراءات المبرمَجة التي أنشأتها من خلال واجهات برمجة تطبيقات Home. |
createAutomation(automation) |
أنشئ مثيلًا لميزة التشغيل الآلي لبنية معيّنة. |
deleteAutomation(automationId) |
يمكنك حذف مثيل عملية التشغيل الآلي حسب رقم تعريفه. |
إنشاء عملية تشغيل آلي
بعد إنشاء مثيل من Home وتلقّي الأذونات من المستخدم، يمكنك الحصول على البنية والأجهزة:
val structure = homeManager.structures().list().single()
val device = homeManager.devices().get(Id("myDevice"))!!
بعد ذلك، حدِّد منطق التشغيل الآلي باستخدام Automation DSL. في واجهات برمجة التطبيقات Home APIs، يتم تمثيل التشغيل الآلي من خلال واجهة Automation
. تحتوي هذه الواجهة
على مجموعة من السمات:
- البيانات الوصفية، مثل الاسم والوصف
- علامات تشير، على سبيل المثال، إلى ما إذا كان يمكن تنفيذ الإجراء المبرمَج أم لا
- قائمة بالعقد التي تحتوي على منطق التشغيل الآلي، وتُعرف باسم
الرسم البياني للتشغيل الآلي، ويتم تمثيلها من خلال السمة
automationGraph
.
يكون automationGraph
تلقائيًا من النوع SequentialFlow
، وهو فئة
تحتوي على قائمة بالعقد التي يتم تنفيذها بترتيب تسلسلي. تمثّل كل عقدة
عنصرًا من عناصر التشغيل الآلي، مثل إجراء التفعيل أو الشرط أو
الإجراء.
خصِّص name
وdescription
للتشغيل الآلي.
يؤدي إنشاء عملية مبرمَجة إلى ضبط العلامة isActive
تلقائيًا على true
، وبالتالي ليس
من الضروري ضبط هذه العلامة صراحةً ما لم تكن تريد في البداية
إيقاف العملية المبرمَجة. في هذا السيناريو، اضبط العلامة على false
أثناء
الإنشاء.
تُستخدَم واجهة DraftAutomation
لإنشاء الإجراءات المبرمَجة وبنائها،
بينما تُستخدَم واجهة Automation
لاستردادها. على سبيل المثال، إليك
Automation DSL لميزة التشغيل التلقائي التي تعمل على تفعيل جهاز عند تفعيل جهاز آخر:
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()) }
}
}
بعد تحديد لغة وصف النص البرمجي للتشغيل الآلي، يجب تمريرها إلى createAutomation()
لإنشاء مثيل DraftAutomation
:
val createdAutomation = structure.createAutomation(automation)
من هنا، يمكنك استخدام جميع طرق التشغيل الآلي الأخرى في التشغيل الآلي، مثل
execute()
وstop()
وupdate()
.
أخطاء التحقق من الصحة
إذا لم يجتَز إنشاء الإجراء المبرمَج عملية التحقّق، ستعرض رسالة تحذير أو خطأ
معلومات عن المشكلة. لمزيد من المعلومات، يُرجى الرجوع إلى
مرجع ValidationIssueType
.
أمثلة على الرموز البرمجية
في ما يلي بعض الأمثلة على الرموز البرمجية التي يمكن استخدامها لتنفيذ أجزاء من الحلول البرمجية الافتراضية الموضّحة في صفحة تصميم حلّ برمجي على Android.
التشغيل الآلي البسيط
عملية التشغيل الآلي التي ترفع الستائر في الساعة 8:00 صباحًا قد يتم تنفيذها على النحو التالي:
// 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.
}
التشغيل الآلي المعقد
عملية التشغيل الآلي التي تشغّل أضواء وامض عند رصد حركة يمكن تنفيذها على النحو التالي:
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())}
}
}
}
}
تنفيذ عملية تشغيل آلي
يمكنك تنفيذ عملية تشغيل آلي تم إنشاؤها باستخدام الطريقة
execute()
:
createdAutomation.execute()
إذا كانت العملية المبرمَجة تحتوي على
مشغِّل يدوي، يبدأexecute()
العملية المبرمَجة من تلك النقطة، مع تجاهل جميع العقد التي تسبق
المشغِّل اليدوي. إذا لم تتضمّن عملية التشغيل الآلي إجراء تفعيل يدويًا، يبدأ التنفيذ
من العقدة التي تليها عقدة التفعيل الأولى.
إذا تعذّرت عملية execute()
، قد يتم طرح HomeException
. اطّلِع على معالجة
الخطأ.
إيقاف عملية تشغيل آلي
يمكنك إيقاف عملية تشغيل آلي باستخدام طريقة stop()
:
createdAutomation.stop()
إذا تعذّرت عملية stop()
، قد يتم طرح HomeException
. اطّلِع على معالجة
الخطأ.
الحصول على قائمة بعمليات التشغيل الآلي لبنية معيّنة
يتمّ تحديد عمليات التشغيل الآلي على مستوى البنية. جمع البيانات في automations()
للوصول إلى Flow
من عمليات التشغيل الآلي:
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"))
}
}
بدلاً من ذلك، يمكنك إسنادها إلى Collection
محلي:
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()
الحصول على عملية تشغيل آلي حسب رقم التعريف
للحصول على عملية تشغيل آلي حسب معرّف العملية الآلية، يمكنك استدعاء الأسلوب
automations()
في البنية، والمطابقة حسب المعرّف:
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()
الردّ:
// 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")
]))
الحصول على عملية تشغيل آلي باسم معيّن
يمكن استخدام الأسلوب
filter()
في Kotlin لتحسين طلبات البيانات من واجهة برمجة التطبيقات. للحصول على عملية تشغيل آلي
حسب الاسم، احصل على عمليات التشغيل الآلي للبنية وفلتِر حسب اسم عملية التشغيل الآلي:
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") }
الحصول على جميع عمليات التشغيل الآلي لجهاز
للحصول على جميع الإجراءات المبرمَجة التي تشير إلى جهاز معيّن، استخدِم الفلترة المُدمجة
لفحص automationGraph
لكل إجراء مبرمَج:
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
}
}
}
تعديل عملية التشغيل الآلي
لتعديل البيانات الوصفية لعملية التشغيل الآلي، يمكنك استدعاء update()
الطريقة، مع تمريرها بتعبير لاmda يضبط البيانات الوصفية:
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" }
تتيح طريقة update()
استبدال الرسم البياني للتشغيل الآلي بالكامل، ولكن لا تتيح تعديل الرسم البياني لكل عقدة. إنّ التعديل لكلّ عقدة معرّض للخطأ بسبب الاعتماد المتبادل بين العقد. إذا
أردت تغيير منطق إحدى الإجراءات المبرمَجة، أنشئ رسمًا بيانيًا جديدًا واستبدِل
الرسم البياني الحالي بالكامل.
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")) }
}
}
}
حذف عملية تشغيل آلي
لحذف قاعدة تشغيل آلي، استخدِم أسلوب
deleteAutomation()
الخاص بالبنية. يجب حذف عملية التشغيل الآلي باستخدام معرّفها.
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)
إذا تعذّر الحذف، قد يتم طرح HomeException
. اطّلِع على معالجة
الخطأ.
تأثير حذف الجهاز في الإجراءات المبرمَجة
إذا حذف مستخدم جهازًا مستخدَمًا في عملية التشغيل الآلي، لن يتمكّن الجهاز المحذوف
من بدء أي عمليات تشغيل، ولن تتمكّن عملية التشغيل الآلي من قراءة السمات
منه أو إصدار أوامر إليه. على سبيل المثال، إذا حذف مستخدم جهاز
OccupancySensorDevice
من منزله، وكان أحد الإجراءات المبرمَجة يتضمّن مشغّلاً يعتمد على
OccupancySensorDevice
، لن يتمكّن هذا المشغّل من تفعيل الإجراء المبرمَج بعد ذلك.