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  2019  2020  <20212022  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  2019  2020  <20212022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Question about http communication by stream device
From: "Zimoch Dirk \(PSI\) via Tech-talk" <tech-talk at aps.anl.gov>
To: "lzfneu at live.com" <lzfneu at live.com>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Tue, 16 Feb 2021 11:22:48 +0000
On Mon, 2021-02-01 at 17:05 +0000, lzf neu via Tech-talk wrote:
> Dear all,
> 
> I have a radiation monitor device simulation program which displays the real time dose rate for 6 channels GM tubes.
> Unfortunately the program only run in windows platform. I intent to grasp the real time dose rate to epics for linux. 
> 
> The protocol is described in details below:
> 
> The communication is based on TCP protocol and the basic information form is JSON and there are six elements in the
> form, five of which is fixed, the sixth element is extensive (JSON form in {"..."})
> 
> The request command is:
> [<ACT>,<SID>,<CID>,<TID>,<DEV>,{"cmd":"X",...}]
> The respond form is:
> [<ACK>,<SID>]
> 
> ACT=Action
> SID=Session ID   "random value by information sponsor used for identify the communication"
> CID=DevID   "Device ID"
> TID=Target ID  "always 0 in the case".
> DEV=Device type  "AREA_Y1 is host name"
> {"cmd":"X",...} is interactive data form.
> 
> Send message:
> ["S","123456","MTS-AY-01",0,"AREA_Y1",{...}]
> the correct respond is:
> ["S","123456", "MTS-AY-01",0,"AREA_Y1",{...}](with data) or ["OK","123456"](without data)
> error respond:
> ["NA","123456"]
> 
> The interactive data form (the sixth element in the above request command) is:
> {"cmd":"X", "addr":"A","length":"YY", "data":[xxxx,xxxx,xxxx,....]}
> cmd: a char
> addr: 1-16 channel of GM tubes, the correspond address is A/B/C/D/E/F/G/H...
> length: the length of data in the [xxxx,xxxx,xxxx,...]
> data: see below.
> 
> a) Get measurement information (cmd:"T")
> Upload real time measurement value of each detectors
> *client to server:
> {"cmd":"T","addr":"A","length":"7","data":[0,0,0.1]}
> 1: int, device status, 0 is normal.
> 2: int, channel 1 status, 0 is normal.
> 3: float, the real time dose rate of channel 1.
> *server to client:
> ["OK","123456"] or ["NA", "123456"]
> 
> b) Get device paramaters (cmd:"R")
> *server to client:
> {"cmd":"R","addr":"0","length":"0","data":""}
> *client to server:
> {"cmd":"R","addr":"0","length":"23","data":["192.168.1.1",8000,6,10]}
> 1: string, ip address of server
> 2: int, port of server
> 3: int, time interval (s) of data restore
> 4: int, alarm recovery time (s)
> 
> My question:
> If I want to get the measurement real time value and device parameters, could the communication between server and
> client be implemented by stream device? 
> Thank you, an example is appreciated.
> 


Yes, that should be possible with StreamDevice. But getting a "random number" is not implemented.

For example to send
["S","123456","MTS-AY-01",0,"AREA_Y1",{...}]
and receive
["OK","123456"]

do this:
set_whatever {
    out '["S","123456","MTS-AY-01",0,"AREA_Y1",{...}]';
    in  '["OK","123456"]';
}

The ... part will probably come from a record and will be formatted with one of the format converters. But as I don't
know what ... is supposed to be, I cannot tell you details.

Taking the {cmd:"R"} example and assuming you still have to add that ["S",... ] stuff, I guess this is what you need:

get_param {
    out '["S","123456","MTS-AY-01",0,"AREA_Y1",{"cmd":"R","addr":"0","length":"0","data":""}]';
    in  '["S","123456", "MTS-AY-01",0,"AREA_Y1",{"cmd":"R","addr":"0","length":"23","data":[%[^]]}]';
}

That would read the part '"192.168.1.1",8000,6,10' as the data payload and store it in the record. Best stringin in this
case. Are you use about the spaces? No space in "123456","MTS-AY-01" in the output but space in "123456", "MTS-AY-01" in
the input?

You probably want to make strings like "MTS-AY-01" and/or "AREA_Y1" configurable. In that case use parameters "\$1",
"\$2" in the protocol and pass those as parameters in the record link:

record (stringin, "PARAM") {
    field (DTYP, "stream")
    field (INP, "@protocolfile get_param(MTS-AY-01,AREA_Y1)
$(PORT)")
}

get_param {
    out '["S","123456","\$1",0,"\$2",  {"cmd":"R","addr":"0","length":"0","data":""}]';
    in  '["S","123456", "\$1",0,"\$2",{"cmd":"R","addr":"0","length":"23","data":[%[^]]}]';
}

Maybe you want to split '192.168.1.1",8000,6,10' into multiple records, let's say keep the IP '192.168.1.1' in one
record and put the port 8000 into another and the other numbers somewhere else.
Also your record may have some device prefix, let's say $(P). In that case, also pass $(P) as a parameter \$1 (shift the
other parameters one up) and use that to redirect input to other records.
The "length":"23" seems to depend on the data payload. We cannot test for that easily, so let's skip it using %*u

record (stringin, "$(P):IP") {
    field (DTYP, "stream")
    field (INP, "@protocolfile get_param($(P),MTS-AY-01,AREA_Y1) 
$(PORT)")
}
record (longin, "$(P):PORT"} {
}
record (longin, "$(P):FIRST"} {
}
record (longin, "$(P):SECOND"} {
}

get_param {
    out '["S","123456","\$2",0,"\$3",  {"cmd":"R","addr":"0","length":"0","data":""}]';
    in  '["S","123456", "\$2",0,"\$3",{"cmd":"R","addr":"0","length":"%*u",'
        '"data":["%[^"]",%(\$1:PORT)u,%(:\$1:FIRST)u,%(\$1:SECOND)u"]}]';
}

I have split the line as you can see for better readability. Simply split the string in two: 'first part' <newline>
'second part'.

BTW: I am using single quotes because you already have double quotes in the string data.

The %[^"] part catches everything which is not a quote, here 192.168.1.1 and sores it in the record
while the
%(\$1:SOMETHING)u parts read an unsigned integer and redirect it to the record \$1:SOMETHING where \$1 is replaced by
whatever the value of the macro $(P) is.

Are your lines terminates in some way (e.g. newline '\n' or return '\r' or both?) In that case set the Terminator
variable, for example: Terminator = "\r\n";  or: Terminator = CR NL;


When writing data, make sure that it always has the same length, so that you can pre-calculate the correct value for
"length":"xxx". For example use "%5u" instead of "%u" to get "    1"  and "12345" instead of variable length "1" and
"12345".


I hope that helps to start,
Dirk



References:
Question about http communication by stream device lzf neu via Tech-talk

Navigate by Date:
Prev: EPICS latest stable version Delahaye Olivier via Tech-talk
Next: Re: EPICS latest stable version Ralph Lange 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  2019  2020  <20212022  2023  2024 
Navigate by Thread:
Prev: Question about http communication by stream device lzf neu via Tech-talk
Next: US ITER seeking Lead Software Engineer Vetter, Kurt G. 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  2019  2020  <20212022  2023  2024 
ANJ, 16 Feb 2021 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·