Hello,
Thank you for your responses.
It is possible to use a just an output record if the record has the info tag asyn:READBACK=1. Then the output record value is updated with a Get operation.
I tried this (using SETs and GETs with separate records) and it seems to work for the SET property commands.
For example, for setting a signed int (as a string), I have:
record(stringout, "INT32S:S")
{
field(DTYP, "asynOctetWrite")
field(OUT, "@asyn($(PORT),0) TEST_INT32S_S")
info(asyn:READBACK, "1")
}
If I monitor (camonitor) the record, and send a value (caput), the value I sent will be immediately displayed.
Then, a few moments later, when the response arrives, it will update accordingly:
INT32S:S 2019-02-04 17:28:21.653208
INT32S:S 2019-02-04 17:28:40.056585 aaa ##value sent, which will be rejected by the device (is not an integer!)
INT32S:S 2019-02-04 17:28:42.663142 18 bad integer ##response received from the device, with an error
This seems to be fine, for what I wanted!
Anyway, is there a way to avoid updating the record, before the readback is executed (in this case, the 'aaa' would not be displayed) ?
-----------
For GET commands it got a bit more complicated...
At first, I tested it with an input record (stringin), with SCAN=Passive. And with this, I expected the record to be processed when I used caget.
However, I noticed that the 'readOctet' was never being run, so the value stayed the same. After reading the documentation, it seems to me that this is not possible unless I "trigger" the processing of the record (by running caput, or by linking to it
from another record with PP).
Is there a way to - always - trigger the processing of an input record when do a get, like using caget?
Anyway, I found a solution that works, and it is probably what you were proposing:
If I treat the GET commands with output records (like I did for SET), then I just have to apply the same recipe:
record(stringout, "INT32S:G")
{
field(DTYP, "asynOctetWrite")
field(OUT, "@asyn($(PORT),0) TEST_INT32S_G")
info(asyn:READBACK, "1")
}
In this case, by using caput I can trigger the sending of a GET command (handled also by writeOctet), and when the responses arrives to the read thread, it will update the record through the readback.
The only issue I have is that it is a bit counter-intuitive to use a output record for a GET command. But it works.
Is this what you were suggesting?
Best regards,
Joao
From: Mark Rivers [[email protected]]
Sent: 31 January 2019 23:18
To: 'Eric Norum'
Cc: Joao Afonso; [email protected]
Subject: RE: AsynDriver with delayed and async communication
>> You really don’t need the SET response record because that information be set in the STAT and SEVR of the SET record.
Ø
Perhaps, but I don’t see how the SET command would get its response — the network input port/stream is tied up by the read thread, right? Or do SET and GET commands use separate ports? Also, if SET commands can be ’slow’ then their responses
woud be better handled by a read thread.
My mistake, I forgot that the SET message takes a long time to reply so its response also needs to be handled by the read thread.
The output record can get its STAT and SEVR updated from the polling thread, but only if it has the asyn:READBACK info tag. See the asyn/testErrorsApp for an example. So a single record can still work to hold the Set value, Set status,
Get value, and Get status. If the Set and the Get generate different errors the STAT will toggle between them.
Mark
On Jan 31, 2019, at 10:08 AM, Mark Rivers via Tech-talk <[email protected]> wrote:
Ø Then, if am correct, this means I will require 2 records for each command, right?
Ø One (for ex. stringout) to send the command and other (ex. stringin) to capture the
responses with I/O Intr.
In my drivers I generally use 2 records, one for the Set (ao, longout, stringout, mbbo, etc.) and one for the Get (ai, longin, stringin, mbbi, etc.).
If you write an asynPortDriver then your records would normally not be stringout and stringin, they would be the records hold the underlying data type of the property (ao/ai, bo/bi, mbbo/mbbi, stringout/stringin only for string parameters).
The driver formats these into strings for Sets and parses the response for Gets.
It is possible to use a just an output record if the record has the info tag asyn:READBACK=1. Then the output record value is updated with a Get operation. I think it’s generally better to use 2 records since you then have independent
error status of the Set and Put operations. You can also see on the OPI display if the Get value does not match the Set value, because of things like out-of-bounds, truncation/rounding, etc.
If the second option is also not possible, then 4 records may be necessary for each property:
- For SET response with IO Intr
- For GET response with IO Intr
You really don’t need the SET response record because that information be set in the STAT and SEVR of the SET record.
Perhaps, but I don’t see how the SET command would get its response — the network input port/stream is tied up by the read thread, right? Or do SET and GET commands use separate ports? Also, if SET commands can be ’slow’ then their responses
woud be better handled by a read thread.
You don’t need the GET command record, that string is constructed in the driver.
I’ve found it useful to have a ’trigger readback’ record. That makes it easy to control the rate at which readbacks are requested.
So my $0.02 is that it’s best to have four records. Although perhaps s single ’trigger readback’ record could be used to request a number of responses.