Execute a Method
Every operation of this application - matching, template creation and module management - is started the same way, and reports its outcome the same way.
The shape of an operation
An operation lives under its own address and always has three parts:
<operation>/execute write here to run it <operation>/input/... the values it works on <operation>/output/status-code what happened, as a number <operation>/output/status-text what happened, in words
Some operations have more under output/ - a match result, or the path of a written file - but
execute, status-code and status-text are always there.
Running an operation
-
Write the input nodes.
-
Write to
execute. The value does not matter; the write itself triggers the operation. -
Read
output/status-codeto find out whether it worked.
Writing to execute is a blocking call: it returns when the operation has finished, so there is
no need to poll a "ready" flag or track state in your program. Inputs keep their values between
runs, so a repeated operation only needs step 2.
Checking the outcome
output/status-code is a signed number, and the sign alone tells you whether it worked:
| Value | Meaning |
|---|---|
greater than 0 |
The operation succeeded |
0 |
The operation has not run since the application started |
less than 0 |
The operation failed and produced nothing |
So the check in a PLC is simply status-code < 0. You only need a specific code when you want to
react differently to different failures - a missing template, say, versus a camera that is not
answering.
output/status-text carries the same outcome as a sentence, and names the offending value when
there is one:
ok: 3 match(es) using 'screw.png' error: crop/startX + crop/width (100 + 900 = 1000) exceeds the image width 640
Read it when something goes wrong; do not build logic on it, because the wording can change between releases. The full list of codes is in Execution Status.
|
The reason arrives on The same text is written to the application log, so a failure is also diagnosable without touching
the Data Layer at all: on ctrlX OS in the ctrlX Logbook or with |
One operation at a time
A module runs one operation at a time. Starting a second one while the first is still running does
not queue it - it returns immediately with status code -1 (busy) and does nothing. The write itself
answers TooManyOperations (ctrlX: DL_TOO_MANY_OPERATIONS), see
One operation at a time.
The lock is per module, so different modules match in parallel - a second camera is not held up by
the first. system/create-object has its own lock, so creating a template does not block matching
and two creations cannot race.
The outputs belong to the run that is starting
Every method clears its own output nodes as soon as it begins - find-object its
output/result, create-object its output/object-path. They are cleared before anything
that can fail, so a run that fails for any reason leaves them empty rather than holding what an
earlier run produced.
That is what makes it safe to read an output without checking output/status-code first: what you
see is either this run’s work or nothing, never a stale value from a previous image.
output/status-code and output/status-text are the exception - they always describe the latest
attempt, which is the whole point of them.
|
Read an output before triggering the next run. The outputs describe the most recent run, and the
next call empties them the moment it starts. Calling The one case that does not clear anything is a call rejected as
Wait for |