Including Looping in Scripts
The script DSL supports a variety of looping constructs to satisfy different use cases:
- loop
- waitFor
- loopAsync
loop - With Default loop Interval
The loop
DSL allows you to start a “blocking” loop so that the rest of the code after loop will not be executed until a stopWhen
condition written inside loop becomes true. You can use this DSL when you want to iteratively perform some actions until a certain condition becomes true. An interval can be provided to set the minimum period of the loop, where every iteration of the loop wait at least for the minimum provided interval before executing the next iteration. If no period is provided, the default interval is 50 milliseconds
.
The following example demonstrates the usage of the loop
DSL with the default interval. In the loop body, a motor is being “moved” by 10 degrees in every iteration of the loop. The loop will be terminated when motor’s current position reaches the expected position of 100 degrees.
- Kotlin
-
source
var motorPosition = 0 fun moveMotor(degrees: Int) { // move motor logic motorPosition += degrees } onSetup("move-motor") { val expectedMotorPosition = 100 // move motor by 10 degrees in each iteration, default loop interval is 50 millis // stop loop when current motor position matches expected motor position and continue with the execution of rest of the handler loop { moveMotor(10) stopWhen(motorPosition == expectedMotorPosition) } }
loop - With Custom Minimum Loop Interval
The following example demonstrates the usage of the loop
DSL when providing a custom loop interval.
- Kotlin
-
source
onSetup("move-motor") { val expectedMotorPosition = 100 // move motor by 20 degrees in every iteration after a loop interval of 500 millis (custom loop interval used here) // stop loop when current motor position matches expected motor position and continue with the execution of rest of the handler loop(minInterval = 500.milliseconds) { moveMotor(20) stopWhen(motorPosition == expectedMotorPosition) } }
minInterval
needs to be greater than default interval of 50 milliseconds
otherwise it will be ignored and default loop interval will be used.
waitFor - Loop Until a Condition is True
This is a specialized version of loop and satisfies simple use cases where you want to semantically block the execution until certain condition becomes true.
In the following example, initializeMotor
method will start the initialization and eventually set motorUp
flag to true indicating motor is successfully initialized. waitFor { motorUp }
will check the value of motorUp
flag every 50 milliseconds
, and when it is true, the rest of the code execution will continue.
- Kotlin
-
source
var motorUp = false fun initializeMotor() { // some motor initialization logic goes here motorUp = true } onSetup("init-motor") { // start initializing motor and this method will set motorUp flag to true once initialization is successful initializeMotor() // pauses the init-motor command handlers execution until motor becomes up waitFor { motorUp } // rest of the handler implementation (here you can safely assume that motor is up) }
loopAsync - With a Default Loop Interval
The previous DSL loop constructs “block” until the loop completes. You can use this DSL when you want to iteratively perform some actions in the background. Since it is asynchronous, once the code in the background loop starts, the code written after loopAsync
will be executed immediately and concurrently.
Like loop
, loopAsync
will be terminated when a stopWhen
condition written inside loop becomes true. loopAsync
also has a default interval of 50 milliseconds
.
The following example demonstrates the usage of loopAsync
DSL with the default interval. In the loop body, a current temperature event is published every 50 milliseconds
. The loopAsync
will be terminated when stopPublishingTemperature
flag becomes true, which is set to true in the onStop
handler.
- Kotlin
-
source
var stopPublishingTemperature = false val temperatureEvent = SystemEvent("IRIS.motor", "temperature") val temperatureKey = longKey("temperature") fun getCurrentTemp(): Long = TODO() // start background loop which publishes current temperature of motor every 50 milliseconds (default loop interval) loopAsync { val currentTemp = getCurrentTemp() publishEvent(temperatureEvent.add(temperatureKey.set(currentTemp))) stopWhen(stopPublishingTemperature) } onStop { stopPublishingTemperature = true }
loopAsync - With a Custom Loop Interval
The following example demonstrates the usage of loopAsync
DSL with a custom loop interval specified.
- Kotlin
-
source
// start background loop which publishes current temperature of motor every 100 milliseconds loopAsync(minInterval = 100.milliseconds) { val currentTemp = getCurrentTemp() publishEvent(temperatureEvent.add(temperatureKey.set(currentTemp))) stopWhen(stopPublishingTemperature) }