EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: AsynDriver with delayed and async communication
From: Joao Afonso via Tech-talk <[email protected]>
To: Mark Rivers <[email protected]>, 'Eric Norum' <[email protected]>
Cc: Stephen Page <[email protected]>, "[email protected]" <[email protected]>
Date: Tue, 5 Feb 2019 13:05:36 +0000
In this case, the main usage would be to trigger the sending of a SET command and, if necessary, hold the error returned by the response to that SET command.

But since it can hold the value, it could also be used by a client to see what was the last SET value. For example, to debug what was the problem when an error was returned.
________________________________________
From: Mark Rivers [[email protected]]
Sent: 05 February 2019 13:24
To: Joao Afonso; 'Eric Norum'
Cc: [email protected]; Stephen Page
Subject: Re: AsynDriver with delayed and async communication

> 1) Output record to trigger a SET command (it would store the SET value for future inspection, and also if any error was returned for this SET - using asyn:READBACK).

This record needs to not just trigger the SET command, but hold the SET value, correct?



________________________________
From: Joao Afonso <[email protected]>
Sent: Tuesday, February 5, 2019 5:10 AM
To: Mark Rivers; 'Eric Norum'
Cc: [email protected]; Stephen Page
Subject: RE: AsynDriver with delayed and async communication

Hello Mark and Andrew,

Thank you for your clarification. It helped me understand better how EPICS is intended to be used.

  *   No, and this is fairly fundamental to the design of EPICS and Channel Access; a get request should not affect the state of the IOC, so you can always query the state of your process database from outside without fear of changing it.

I completely agree with this approach, and it is what makes sense for most databases.
However it collides with the way how this specific device works:

It is quite complex, and internally it stores the state of all properties. It can change them as well, anytime.
Therefore, if I set a property with a value, some seconds later it may already have a different one.

This means that when I ask the IOC for a record value, it has to send the GET command to the device, wait (asynchronously, not blocking other callbacks) for the response, and only after that update the record value according to the response.

  *   If there are other non-EPICS mechanisms by which the device parameters can be changed then you would probably want to process the GET records at some periodic scan rate so your users can see when those external changes have happened.

In our case scanning periodically is not an option. It has to be done on demand.
The reason is that there may be dozens (or even hundreds) of properties, some of them expensive to process, so constant polling can be a big overhead for the device.

  *   If you want to tell the driver to read a particular value “now” then you do need an output record to the driver to do that.

It seems to me that the solution will be something like this.
Maybe I can have 3 records for each property:

1) Output record to trigger a SET command (it would store the SET value for future inspection, and also if any error was returned for this SET - using asyn:READBACK).
2) Output record to trigger a GET command (if an error is returned by the device for this GET, it will also store it).
3) Input record (I/O Intr) with the last successful GET or SET value, updated only when a valid response from the device arrives.

I think this respects the separation of gets/sets that you both mentioned, while allowing a client to monitor the most recent value without having to constantly poll the device. It is also compatible with the asynchronous communication requirement.

What is your opinion?

I just want to design this module in a way that uses our protocol efficiently, but also respects all EPICS development best practices.

Thanks again,
Joao

________________________________
From: Mark Rivers [[email protected]]
Sent: 04 February 2019 22:48
To: Joao Afonso; 'Eric Norum'
Cc: [email protected]
Subject: RE: AsynDriver with delayed and async communication


Hi Joao,



Andrew has already answered many of your questions.



Ø  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?



What I was suggesting was that the records would all be ao/ai, bo/bi, longout/longin, mbbo/mbbi, etc. records in user units (volts, degrees, etc.).  Those records communicate with the asynPortDriver.  The asynPortDriver constructs the strings and writes and reads them with asynOctetSyncIO.  That way there are not output records to do a read, except perhaps a single bo record that tells the driver “read all inputs now”.  The driver then builds and sends the strings to the device.  The driver could also be set to poll at a user-defined rate, where the polling rate is set by an ao record.  If you want to tell the driver to read a particular value “now” then you do need an output record to the driver to do that.



Mark







From: Joao Afonso <[email protected]>
Sent: Monday, February 4, 2019 11:51 AM
To: Mark Rivers <[email protected]>; 'Eric Norum' <[email protected]>
Cc: [email protected]
Subject: RE: AsynDriver with delayed and async communication



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]<mailto:[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







From: Eric Norum <[email protected]<mailto:[email protected]>>
Sent: Thursday, January 31, 2019 12:22 PM
To: Mark Rivers <[email protected]<mailto:[email protected]>>
Cc: Joao Afonso <[email protected]<mailto:[email protected]>>; [email protected]<mailto:[email protected]>
Subject: Re: AsynDriver with delayed and async communication



On Jan 31, 2019, at 10:08 AM, Mark Rivers via Tech-talk <[email protected]<mailto:[email protected]>> wrote:



Hi Joao,



>  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 command

- For SET response with IO Intr

- For GET command

- 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.

--
Eric Norum
[email protected]<mailto:[email protected]>





References:
AsynDriver with delayed and async communication Joao Afonso via Tech-talk
RE: AsynDriver with delayed and async communication Joao Afonso via Tech-talk
RE: AsynDriver with delayed and async communication Mark Rivers via Tech-talk
Re: AsynDriver with delayed and async communication Eric Norum via Tech-talk
RE: AsynDriver with delayed and async communication Mark Rivers via Tech-talk
RE: AsynDriver with delayed and async communication Joao Afonso via Tech-talk
RE: AsynDriver with delayed and async communication Mark Rivers via Tech-talk
RE: AsynDriver with delayed and async communication Joao Afonso via Tech-talk
Re: AsynDriver with delayed and async communication Mark Rivers via Tech-talk

Navigate by Date:
Prev: RE: Weird stream device behavior when using the IOC shell's exit function Abdalla Ahmad via Tech-talk
Next: Re: Weird stream device behavior when using the IOC shell's exit function Mark Rivers via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: AsynDriver with delayed and async communication Mark Rivers via Tech-talk
Next: I would like to try the "BEAST". Williams Jr., Ernest L. via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  <20192020  2021  2022  2023  2024 
ANJ, 05 Feb 2019 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·