SICS-128: Added a reactor status protocol handler called OPALSTAT for the asyncqueue.
OPALSTAT uses HTTP/1.1 and sets the UserAgent to SICS to avoid re-directs. It also sends the SICS version and revision numbers in the UserAgent string.
This commit is contained in:
147
site_ansto/hardsup/aqp_opalstatus.c
Normal file
147
site_ansto/hardsup/aqp_opalstatus.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* @file aqp_opalstatus.c
|
||||||
|
* @brief
|
||||||
|
* Implements a simple protocol to GET reactor status using an HTTP/1.1 GET.
|
||||||
|
* It sets the UserAgent as SICS to avoid re-directs because we don't handle them.
|
||||||
|
* If the HTTP status is not OK then it returns the status in the data buffer.
|
||||||
|
*/
|
||||||
|
#include "../made_config.h"
|
||||||
|
#include <sics.h>
|
||||||
|
#include <asyncqueue.h>
|
||||||
|
|
||||||
|
#define HTTP_OK "HTTP/1.1 200 OK"
|
||||||
|
#define HTTP11 " HTTP/1.1\r\n"
|
||||||
|
#if defined SICS_VERSION && defined SICS_REVISION
|
||||||
|
#define USERAGENT "User-Agent: SICS Version = " SICS_VERSION " Revision = " SICS_REVISION "\r\n"
|
||||||
|
#else
|
||||||
|
#define USERAGENT "User-Agent: SICS\r\n"
|
||||||
|
#endif
|
||||||
|
#define HOST "Host: neutron.ansto.gov.au\r\n"
|
||||||
|
|
||||||
|
enum replystates {START, HEADER, CHKHEADEREND, MSG};
|
||||||
|
static pAsyncProtocol OPAL_Protocol = NULL;
|
||||||
|
|
||||||
|
static int OPAL_Tx(pAsyncProtocol p, pAsyncTxn txn) {
|
||||||
|
if (txn == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
txn->txn_status = ATX_ACTIVE;
|
||||||
|
if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The header and message are followed by the character sequences given below,
|
||||||
|
* HEADER cr lf cr lf <msg len> cr lf
|
||||||
|
* MESSAGE cr lf 0x30 cr lf cr lf
|
||||||
|
* So we assume that the header is terminated by two consecutive crlf char
|
||||||
|
* pairs which are eventually followed by another crlf
|
||||||
|
* The message is assumed to be terminated by a crlf pair eventually followed
|
||||||
|
* by two more crlf pairs of characters
|
||||||
|
* Processing is simplified by discarding cr chars and counting lf chars */
|
||||||
|
static int OPAL_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
|
||||||
|
int ret = 1;
|
||||||
|
static int nlctr = 0;
|
||||||
|
static enum replystates state = START;
|
||||||
|
|
||||||
|
if (ch == '\r') {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
switch (state) {
|
||||||
|
case START:
|
||||||
|
if (ch == '\n') {
|
||||||
|
/* check HTTP status */
|
||||||
|
if ( strncmp(txn->inp_buf, HTTP_OK, strlen(HTTP_OK) ) == 0 ) {
|
||||||
|
txn->inp_idx = 0;
|
||||||
|
nlctr = 0;
|
||||||
|
state = HEADER;
|
||||||
|
} else
|
||||||
|
ret = AQU_POP_CMD;
|
||||||
|
} else if (txn->inp_idx < txn->inp_len)
|
||||||
|
txn->inp_buf[txn->inp_idx++] = ch;
|
||||||
|
else
|
||||||
|
ret = AQU_POP_CMD;
|
||||||
|
break;
|
||||||
|
case HEADER:
|
||||||
|
if (ch == '\n') {
|
||||||
|
nlctr++;
|
||||||
|
state = CHKHEADEREND;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHKHEADEREND:
|
||||||
|
if (nlctr == 1 && ch == '\n')
|
||||||
|
nlctr++;
|
||||||
|
else if (nlctr == 1 && ch != '\n') {
|
||||||
|
txn->inp_idx = 0;
|
||||||
|
nlctr = 0;
|
||||||
|
state = HEADER;
|
||||||
|
} else if (nlctr == 2 && ch == '\n') {
|
||||||
|
txn->inp_idx = 0;
|
||||||
|
nlctr = 0;
|
||||||
|
state = MSG;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MSG:
|
||||||
|
if (txn->inp_idx >= txn->inp_len)
|
||||||
|
ret = AQU_POP_CMD;
|
||||||
|
if (nlctr == 0 && ch != '\n')
|
||||||
|
txn->inp_buf[txn->inp_idx++] = ch;
|
||||||
|
else if (nlctr == 2 && ch == '\n')
|
||||||
|
ret = AQU_POP_CMD;
|
||||||
|
else
|
||||||
|
nlctr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret == AQU_POP_CMD) {
|
||||||
|
nlctr = 0;
|
||||||
|
state = START;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OPAL_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
|
||||||
|
if (event == AQU_TIMEOUT) {
|
||||||
|
pTxn->txn_status = ATX_TIMEOUT;
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
|
return AQU_POP_CMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append HTTP/1.1 and Host: line to message */
|
||||||
|
static int OPAL_PrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char* cmd, int cmd_len, int rsp_len) {
|
||||||
|
int msglen;
|
||||||
|
|
||||||
|
msglen = cmd_len + strlen(HTTP11) + strlen(USERAGENT) + strlen(HOST) + 3;
|
||||||
|
txn->out_buf = (char*) malloc(msglen);
|
||||||
|
if (txn->out_buf == NULL) {
|
||||||
|
SICSLogWrite("ERROR: Out of memory in OPAL_PrepareTxn", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strcpy(txn->out_buf, cmd);
|
||||||
|
strcat(txn->out_buf, HTTP11);
|
||||||
|
strcat(txn->out_buf, USERAGENT);
|
||||||
|
strcat(txn->out_buf, HOST);
|
||||||
|
strcat(txn->out_buf, "\r\n");
|
||||||
|
txn->out_len = msglen;
|
||||||
|
txn->out_idx = 0;
|
||||||
|
if (txn->inp_buf != NULL) {
|
||||||
|
free(txn->inp_buf);
|
||||||
|
}
|
||||||
|
txn->inp_len = rsp_len;
|
||||||
|
txn->inp_idx = 0;
|
||||||
|
txn->txn_state = 0;
|
||||||
|
txn->txn_status = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpalStatusInitProtocol(SicsInterp *pSics) {
|
||||||
|
if (OPAL_Protocol == NULL) {
|
||||||
|
OPAL_Protocol = AsyncProtocolCreate(pSics, "OPALSTAT", NULL, NULL);
|
||||||
|
OPAL_Protocol->sendCommand = OPAL_Tx;
|
||||||
|
OPAL_Protocol->handleInput = OPAL_Rx;
|
||||||
|
OPAL_Protocol->killPrivate = NULL;
|
||||||
|
OPAL_Protocol->handleEvent = OPAL_Ev;
|
||||||
|
OPAL_Protocol->prepareTxn = OPAL_PrepareTxn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
site_ansto/hardsup/aqp_opalstatus.h
Normal file
4
site_ansto/hardsup/aqp_opalstatus.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef AQP_OPALSTATUS_H
|
||||||
|
#define AQP_OPALSTATUS_H
|
||||||
|
void OpalStatusInitProtocol(SicsInterp *pSics);
|
||||||
|
#endif
|
@ -34,6 +34,7 @@ HOBJ += sct_lfprot.o
|
|||||||
HOBJ += camera.o
|
HOBJ += camera.o
|
||||||
HOBJ += cameradriver.o
|
HOBJ += cameradriver.o
|
||||||
HOBJ += sct_asyncqueue.o
|
HOBJ += sct_asyncqueue.o
|
||||||
|
HOBJ += aqp_opalstatus.o
|
||||||
|
|
||||||
libhlib.a: $(HOBJ)
|
libhlib.a: $(HOBJ)
|
||||||
rm -f libhlib.a
|
rm -f libhlib.a
|
||||||
|
@ -12,8 +12,8 @@ driver reactor_status = {
|
|||||||
var status = {
|
var status = {
|
||||||
type = text;
|
type = text;
|
||||||
priv = spy;
|
priv = spy;
|
||||||
readable = 10;
|
readable = 30;
|
||||||
read_command = 'GET /Bragg/proposal/reactor.jsp?type=ALL HTTP/1.0';
|
read_command = 'GET /Bragg/proposal/reactor.jsp?type=ALL';
|
||||||
read_function = rdAll;
|
read_function = rdAll;
|
||||||
fetch_function = getState;
|
fetch_function = getState;
|
||||||
data = false;
|
data = false;
|
||||||
|
@ -252,7 +252,7 @@ proc ::scobj::reactor_status::mk_sct_reactor_status { sct_controller name } {
|
|||||||
hsetprop ${scobj_hpath}/power nxalias "${name}_power"
|
hsetprop ${scobj_hpath}/power nxalias "${name}_power"
|
||||||
|
|
||||||
hfactory ${scobj_hpath}/status plain spy text
|
hfactory ${scobj_hpath}/status plain spy text
|
||||||
hsetprop ${scobj_hpath}/status read ${ns}::getState ${scobj_hpath} rdAll {GET /Bragg/proposal/reactor.jsp?type=ALL HTTP/1.0}
|
hsetprop ${scobj_hpath}/status read ${ns}::getState ${scobj_hpath} rdAll {GET /Bragg/proposal/reactor.jsp?type=ALL}
|
||||||
hsetprop ${scobj_hpath}/status rdAll ${ns}::rdAll ${scobj_hpath}
|
hsetprop ${scobj_hpath}/status rdAll ${ns}::rdAll ${scobj_hpath}
|
||||||
hsetprop ${scobj_hpath}/status control false
|
hsetprop ${scobj_hpath}/status control false
|
||||||
hsetprop ${scobj_hpath}/status data false
|
hsetprop ${scobj_hpath}/status data false
|
||||||
@ -289,7 +289,7 @@ proc ::scobj::reactor_status::mk_sct_reactor_status { sct_controller name } {
|
|||||||
hsetprop ${scobj_hpath} data "true"
|
hsetprop ${scobj_hpath} data "true"
|
||||||
|
|
||||||
if {[SplitReply [opal_simulation]]=="false"} {
|
if {[SplitReply [opal_simulation]]=="false"} {
|
||||||
${sct_controller} poll ${scobj_hpath}/status 10
|
${sct_controller} poll ${scobj_hpath}/status 30
|
||||||
}
|
}
|
||||||
hsetprop ${scobj_hpath} klass NXsource
|
hsetprop ${scobj_hpath} klass NXsource
|
||||||
# hook code starts
|
# hook code starts
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
fileeval $cfPath(source)/sct_reactor_status.tcl
|
fileeval $cfPath(source)/sct_reactor_status.tcl
|
||||||
|
|
||||||
if {[SplitReply [opal_simulation]]=="false"} {
|
if {[SplitReply [opal_simulation]]=="false"} {
|
||||||
MakeAsyncProtocol std
|
MakeAsyncQueue aqreactor OPALSTAT neutron.ansto.gov.au 80
|
||||||
std sendterminator \r\n\r\n
|
|
||||||
std replyterminator 0x03
|
|
||||||
MakeAsyncQueue aqreactor std portal.nbi.ansto.gov.au 80
|
|
||||||
aqreactor timeout 2000
|
aqreactor timeout 2000
|
||||||
}
|
}
|
||||||
add_reactor_status source aqadapter aqreactor
|
add_reactor_status source aqadapter aqreactor
|
||||||
|
@ -16,7 +16,7 @@ set quieckport 60004
|
|||||||
# icsval column = settings when running on the Instrument Control Server (ie SICS_SIMULATION not defined)
|
# icsval column = settings when running on the Instrument Control Server (ie SICS_SIMULATION not defined)
|
||||||
# fakedev column = settings for test platforms (ie SICS_SIMULATION=fakedev)
|
# fakedev column = settings for test platforms (ie SICS_SIMULATION=fakedev)
|
||||||
foreach {simflag icsval fakedev} {
|
foreach {simflag icsval fakedev} {
|
||||||
opal_simulation true true
|
opal_simulation false true
|
||||||
detector_simulation false true
|
detector_simulation false true
|
||||||
hmm_simulation false true
|
hmm_simulation false true
|
||||||
environment_simulation false true
|
environment_simulation false true
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include "lssmonitor.h"
|
#include "lssmonitor.h"
|
||||||
#include "beamstopaction.h"
|
#include "beamstopaction.h"
|
||||||
#include "cameradriver.h"
|
#include "cameradriver.h"
|
||||||
|
#include "aqp_opalstatus.h"
|
||||||
|
|
||||||
/*@observer@*//*@null@*/ pCounterDriver CreateMonCounter(/*@observer@*/SConnection *pCon, /*@observer@*/char *name, char *params);
|
/*@observer@*//*@null@*/ pCounterDriver CreateMonCounter(/*@observer@*/SConnection *pCon, /*@observer@*/char *name, char *params);
|
||||||
|
|
||||||
@ -351,6 +352,7 @@ static void AddCommands(SicsInterp *pInter)
|
|||||||
ORHVPSInitProtocol(pInter);
|
ORHVPSInitProtocol(pInter);
|
||||||
LS340InitProtocol(pInter);
|
LS340InitProtocol(pInter);
|
||||||
CameraInitProtocol(pInter);
|
CameraInitProtocol(pInter);
|
||||||
|
OpalStatusInitProtocol(pInter);
|
||||||
AddCommand(pInter,"InstallProtocolHandler", InstallProtocol,NULL,NULL);
|
AddCommand(pInter,"InstallProtocolHandler", InstallProtocol,NULL,NULL);
|
||||||
AddCommand(pInter,"hostnam",hostNamCmd,NULL,NULL);
|
AddCommand(pInter,"hostnam",hostNamCmd,NULL,NULL);
|
||||||
AddCommand(pInter,"portnum",portNumCmd,NULL,NULL);
|
AddCommand(pInter,"portnum",portNumCmd,NULL,NULL);
|
||||||
|
Reference in New Issue
Block a user