Skip to content

Commit

Permalink
Sy 1216 document new controller wait conditions (#827)
Browse files Browse the repository at this point in the history
* [docs/site] - improved documentation for new controller methods

* [docs/site] - removed extra dividers
  • Loading branch information
emilbon99 committed Sep 15, 2024
1 parent 1ca6e7b commit f82b5ed
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
2 changes: 1 addition & 1 deletion client/py/synnax/control/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def wait_until(
"""
return self._internal_wait_until(cond, timeout)

def while_true(
def wait_while(
self,
cond: Callable[[Controller], bool],
timeout: CrudeTimeSpan = None,
Expand Down
4 changes: 2 additions & 2 deletions client/py/tests/test_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def daq(ev: threading.Event):
assert assertions["seq_second_ack"]
assert assertions["remained_true"]

def test_while_true(self, client: sy.Synnax):
def test_wait_while(self, client: sy.Synnax):
"""Test that the controller can wait for a condition to be true for a certain amount of time"""
press_end_cmd_time, press_en_cmd, press_en, daq_time = create_valve_set(client)

Expand Down Expand Up @@ -318,7 +318,7 @@ def is_closed(auto):
c += 1
return not auto[press_en.key]

remained_true = auto.while_true(is_closed)
remained_true = auto.wait_while(is_closed)
assertions["remained_true"] = remained_true
assertions["remained_true_count"] = c

Expand Down
3 changes: 0 additions & 3 deletions docs/site/src/pages/reference/concepts/writes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,6 @@ never share the same timestamp, and cannot share the same index.
It's almost always necessary to use a separate index for each command channel, or use a
virtual channel that does not require an index.

<Divider.Divider direction="x" />


<Divider.Divider direction="x" />

## Dynamic Control - Write Authorities
Expand Down
83 changes: 78 additions & 5 deletions docs/site/src/pages/reference/control/sequence-basics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: "@/layouts/MainLayout.astro"
title: "Control Sequences"
heading: "Control Sequence Basics"
---
import { Divider } from "@synnaxlabs/pluto";
import { Divider, Note } from "@synnaxlabs/pluto";
import { Image } from "@/components/Media";
import Table from "@/components/Table.astro";
import Code from "@/components/code/Code.astro";
Expand All @@ -18,8 +18,11 @@ process of writing your first control sequence.

## Prerequisites

Before you can start writing control sequences, you'll need to have the Synnax Python
client installed
Before you can start writing control sequences, you'll need to have:

- A Synnax [cluster](/reference/cluster/quick-start) running
- The Synnax [Python Client](/reference/python-client/get-started) installed


<Divider.Divider direction="x" />

Expand Down Expand Up @@ -123,7 +126,7 @@ The `wait_until` method allows you to wait for a condition to be met before cont
This method accepts a function that takes in the current sensor values and returns
a boolean.

#### Lambda Expressions
### Lambda Expressions

We recommend relying on `lambda` expressions to keep your code simple. A
lambda expression is a simple way to define a function in one line. Here's an example
Expand Down Expand Up @@ -152,7 +155,7 @@ with client.control.acquire(
controller.wait_until(lambda sv: sv["pressure_1"] > 25)
```

#### Adding a Timeout
### Adding a Timeout

The `wait_until` method will continuously check the condition on every new value until
it returns `True`. If you'd like to add a timeout to the wait, you can pass in a `timeout`
Expand All @@ -169,4 +172,74 @@ method:
timed_out = controller.wait_until(lambda sv: sv["pressure_1"] > 25, timeout=10)
if timed_out:
print("The condition timed out")
```

<Divider.Divider direction="x" />

## Blocking While a Condition is True

The `wait_while` method allows you to block the control sequence until a condition is
no longer true. This method is useful for waiting for a sensor value to reach a certain
point before continuing. Here's an example of how you can use the `wait_while` method:

```python
with client.control.acquire(
read=["pressure_1", "daq_do_1_state"],
write=["daq_do_1_cmd"]
write_authorities=[sy.Authority.ABSOLUTE]
) as controller:
# Wait until the pressure sensor value is above 25
controller.wait_while(lambda sv: sv["pressure_1"] < 25)
```

In many ways, you can think of the `wait_while` method as the opposite of the `wait_until`
method.

<Divider.Divider direction="x" />

## Asserting a Condition Remains True

The `remains_true_for` method allows you to assert that a condition remains true for a
certain duration. This method is useful for ensuring that a sensor value remains within
a certain range for a period of time. Here's an example of how you can use the
`remains_true_for` method:

```python
with client.control.acquire(
read=["pressure_1", "daq_do_1_state"],
write=["daq_do_1_cmd"]
write_authorities=[sy.Authority.ABSOLUTE]
) as controller:
# Assert that the pressure sensor value remains above 25 for 10 seconds
controller.remains_true_for(lambda sv: sv["pressure_1"] > 25, duration=10)
```

<Note.Note variant="warning">
The `duration` argument should be treated as a minimum duration, as the block is not
guaranteed to sleep for exactly the provided duration. The actual duration may be longer
due to the operating system's scheduler. This block will _not_ sleep for less than the
provided duration unless the condition is no longer true.
</Note.Note>

### Remains True for a Certain Percentage of Samples

The `remains_true_for` method also accepts a `percentage` argument, which is a decimal
value that allows you to specify the percentage of samples that must meet the condition.
This is useful for ensuring that a sensor value remains within a certain range for at
least a certain percentage of the duration. Here's an example of how you can use the
`percentage` argument:

```python
with client.control.acquire(
read=["pressure_1", "daq_do_1_state"],
write=["daq_do_1_cmd"]
write_authorities=[sy.Authority.ABSOLUTE]
) as controller:
# Assert that the pressure sensor value remains above 25 for 10 seconds
# for at least 90% of the samples
controller.remains_true_for(
lambda sv: sv["pressure_1"] > 25,
duration=10,
percentage=0.9
)
```
2 changes: 1 addition & 1 deletion pluto/src/note/Note.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

&.pluto--warning {
background: var(--pluto-warning-z-10);
border-color: var(--pluto-warning-z-);
border-color: var(--pluto-warning-z-70);
}

&.pluto--error {
Expand Down

0 comments on commit f82b5ed

Please sign in to comment.