Skip to content

Commit 997b847

Browse files
committed
update actions
1 parent 086b60c commit 997b847

File tree

1 file changed

+129
-4
lines changed

1 file changed

+129
-4
lines changed

docs/beginners-guide/articles/actions.md

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Only methods decorated with `action()` are exposed to clients.
1111
--8<-- "docs/beginners-guide/code/thing_example_2.py:542:546"
1212
```
1313

14+
## Payload Validation
15+
1416
Arguments are loosely typed and may need to be constrained with a schema based
1517
on the robustness the developer is expecting in their application:
1618

@@ -149,13 +151,132 @@ on the robustness the developer is expecting in their application:
149151

150152
=== "Single Argument"
151153

152-
```py title="Input Schema" linenums="1"
153-
```
154+
```py title="Input Schema with Single Argument" linenums="1"
155+
from typing import Annotated
156+
157+
class GentecOpticalEnergyMeter(Thing):
158+
159+
@action()
160+
def start_acquisition(self,
161+
max_count: Annotated[int, Field(gt=0)]
162+
) -> None:
163+
"""
164+
Start acquisition of energy measurements.
165+
166+
Parameters
167+
----------
168+
max_count: int
169+
maximum number of measurements to acquire before stopping automatically.
170+
"""
171+
```
172+
173+
???+ note "JSON schema seen in Thing Description"
174+
175+
```py
176+
GentecOpticalEnergyMeter.start_acquisition.to_affordance().json()
177+
```
178+
179+
```json
180+
{
181+
"description": "Start acquisition of energy measurements. max_count: maximum number of measurements to acquire before stopping automatically.",
182+
"input": {
183+
"properties": {
184+
"max_count": {
185+
"exclusiveMinimum": 0,
186+
"type": "integer"
187+
}
188+
},
189+
"required": ["max_count"],
190+
"title": "start_acquisition_input",
191+
"type": "object"
192+
},
193+
"synchronous": True
194+
}
195+
```
154196

155197
=== "Multiple Arguments"
156198

157-
```py title="Input Schema with Multiple Arguments" linenums="1"
158-
```
199+
```py title="Input Schema with Multiple Arguments"
200+
from typing import Literal
201+
202+
class Picoscope6000(Thing):
203+
204+
@action()
205+
def set_channel_pydantic(
206+
self,
207+
channel: Literal["A", "B", "C", "D"],
208+
enabled: bool = True,
209+
v_range: Literal[
210+
"10mV",
211+
"20mV",
212+
"50mV",
213+
"100mV",
214+
"200mV",
215+
"500mV",
216+
"1V",
217+
"2V",
218+
"5V",
219+
"10V",
220+
"20V",
221+
"50V",
222+
"MAX_RANGES",
223+
] = "2V",
224+
offset: float = 0,
225+
coupling: Literal["AC", "DC"] = "DC_1M",
226+
bw_limiter: Literal["full", "20MHz"] = "full",
227+
) -> None:
228+
```
229+
230+
???+ note "JSON schema seen in Thing Description"
231+
232+
```json
233+
{
234+
"description": "Set the parameter for a channel. https://www.picotech.com/download/manuals/picoscope-6000-series-a-api-programmers-guide.pdf",
235+
"input": {
236+
"properties": {
237+
"channel": {
238+
"enum": ["A", "B", "C", "D"],
239+
"type": "string"
240+
},
241+
"enabled": {"default": True, "type": "boolean"},
242+
"v_range": {
243+
"default": "2V",
244+
"enum": [
245+
"10mV",
246+
"20mV",
247+
"50mV",
248+
"100mV",
249+
"200mV",
250+
"500mV",
251+
"1V",
252+
"2V",
253+
"5V",
254+
"10V",
255+
"20V",
256+
"50V",
257+
"MAX_RANGES"
258+
],
259+
260+
"type": "string"
261+
},
262+
"offset": {"default": 0, "type": "number"},
263+
"coupling": {
264+
"default": "DC_1M",
265+
"enum": ["AC", "DC"],
266+
"type": "string"
267+
},
268+
"bw_limiter": {
269+
"default": "full",
270+
"enum": ["full", "20MHz"],
271+
"type": "string"
272+
}
273+
},
274+
"required": ["channel"],
275+
"type": "object"
276+
},
277+
"synchronous": True
278+
}
279+
```
159280

160281
However, a schema is optional and it only matters that
161282
the method signature is matching when requested from a client. To enable this, set global attribute `allow_relaxed_schema_actions=True`. This setting is used especially when a schema is useful for validation of arguments but not available - not for methods with no arguments.
@@ -197,3 +318,7 @@ client side, there is no difference between invoking a normal action and an acti
197318
```py title="Custom Validation" linenums="1"
198319
--8<-- "docs/beginners-guide/code/actions/parameterized_function.py:30:36"
199320
```
321+
322+
## Async & Threaded Actions
323+
324+
## TD

0 commit comments

Comments
 (0)