- Added a special el734hp which scales with 1000 for SANSLI - Added another error to the magnet driver: magnet broken
253 lines
7.7 KiB
C
253 lines
7.7 KiB
C
/**
|
|
* This is a module to manage the LMD-400 device used to monitor HRPT detector
|
|
* electronics temperatures and pressures. It is read only. The device sends
|
|
* alarm messages or temperature readings any now and then asynchronously. The
|
|
* format of the messages is:
|
|
* - Alarm message: date time device type of alarm
|
|
* - Data message: 3 lines
|
|
* --- date time
|
|
* --- 001..008 val val val ....
|
|
* --- 009..016 val val ....
|
|
* Please note that the values use a komma as the decimal separator and not a .
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, October 2007
|
|
*/
|
|
#include <sics.h>
|
|
#include <sicsobj.h>
|
|
#include <sicshipadaba.h>
|
|
#include <network.h>
|
|
#include <nwatch.h>
|
|
#include <commandlog.h>
|
|
#include <stptok.h>
|
|
/*
|
|
* possible states
|
|
*/
|
|
#define IDLE 0
|
|
#define WAITDATA1 1
|
|
#define WAITDATA2 2
|
|
/*
|
|
* private data structure
|
|
*/
|
|
#define BUFLEN 1024
|
|
typedef struct {
|
|
int state;
|
|
char host[256];
|
|
int port;
|
|
mkChannel *pSock;
|
|
pNWContext watchContext;
|
|
char lineBuffer[BUFLEN];
|
|
} LMD200, *pLMD200;
|
|
/*----------------------------------------------------------------------------*/
|
|
static void killLMD200(void *data){
|
|
pLMD200 priv = (pLMD200)data;
|
|
if(priv == NULL){
|
|
return;
|
|
}
|
|
if(priv->watchContext != NULL){
|
|
NetWatchRemoveCallback(priv->watchContext);
|
|
}
|
|
if(priv->pSock != NULL){
|
|
NETClosePort(priv->pSock);
|
|
free(priv->pSock);
|
|
}
|
|
free(priv);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static void setAlarm(pSICSOBJ self, char *text){
|
|
hdbValue alarmVal;
|
|
pHdb node = NULL;
|
|
|
|
alarmVal = MakeHdbText(text);
|
|
node = GetHipadabaNode(self->objectNode,"alarm");
|
|
assert(node != NULL);
|
|
UpdateHipadabaPar(node,alarmVal, NULL);
|
|
ReleaseHdbValue(&alarmVal);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void doAlarm(pSICSOBJ self, char *lineBuffer){
|
|
|
|
setAlarm(self,lineBuffer);
|
|
WriteToCommandLog("CERCA>> ", lineBuffer);
|
|
ServerWriteGlobal(lineBuffer,eError);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
extern char *trim(char *);
|
|
|
|
static void storeData(pSICSOBJ self, int start, char *lineBuffer){
|
|
pHdb node = NULL;
|
|
char number[80], *pPtr = NULL, *pKomma;
|
|
|
|
node = GetHipadabaNode(self->objectNode,"data");
|
|
assert(node != NULL);
|
|
/*
|
|
* throw first away
|
|
*/
|
|
pPtr = stptok(lineBuffer,number,80," ");
|
|
pPtr = trim(pPtr);
|
|
pPtr = stptok(pPtr,number,80," ");
|
|
while(pPtr != NULL){
|
|
if(strstr(number,"noinp") != NULL){
|
|
node->value.v.floatArray[start] = -9999.99;
|
|
start++;
|
|
} else {
|
|
pKomma = strchr(number,',');
|
|
if(pKomma != NULL){
|
|
*pKomma = '.';
|
|
}
|
|
pKomma = strchr(number,'(');
|
|
if(pKomma != NULL){
|
|
*pKomma = ' ';
|
|
}
|
|
pKomma = strchr(number,')');
|
|
if(pKomma != NULL){
|
|
*pKomma = ' ';
|
|
}
|
|
node->value.v.floatArray[start] = atof(trim(number));
|
|
start++;
|
|
}
|
|
pPtr = trim(pPtr);
|
|
pPtr = stptok(pPtr,number,80," ");
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int countTokens(char *lineBuffer){
|
|
int count = 0;
|
|
char myBuffer[BUFLEN], token[60];
|
|
char *pPtr = NULL;
|
|
|
|
|
|
memset(myBuffer,0,BUFLEN);
|
|
strcpy(myBuffer, lineBuffer);
|
|
pPtr = myBuffer;
|
|
pPtr = stptok(pPtr,token, 60," \r\n");
|
|
while(pPtr != NULL){
|
|
count++;
|
|
pPtr = trim(pPtr);
|
|
pPtr = stptok(pPtr,token,60," \r\n");
|
|
}
|
|
return count;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void interpretLine(pSICSOBJ self, pLMD200 priv){
|
|
pHdb node = NULL;
|
|
|
|
switch(priv->state){
|
|
case IDLE:
|
|
if(strstr(priv->lineBuffer, "Alarm") != NULL){
|
|
doAlarm(self, priv->lineBuffer);
|
|
return;
|
|
} else if(strstr(priv->lineBuffer,"Pre") != NULL){
|
|
setAlarm(self,priv->lineBuffer);
|
|
} else {
|
|
priv->state = WAITDATA1;
|
|
setAlarm(self,"I do not feel very alarmed");
|
|
return;
|
|
}
|
|
break;
|
|
case WAITDATA1:
|
|
if(strstr(priv->lineBuffer,"...0") == NULL){
|
|
/* this data is out of order, recover...*/
|
|
priv->state == IDLE;
|
|
return;
|
|
}
|
|
storeData(self, 0, priv->lineBuffer);
|
|
priv->state = WAITDATA2;
|
|
break;
|
|
case WAITDATA2:
|
|
if(strstr(priv->lineBuffer,"...0") == NULL){
|
|
/* this data is out of order, recover...*/
|
|
priv->state == IDLE;
|
|
return;
|
|
}
|
|
storeData(self, 8, priv->lineBuffer);
|
|
priv->state = IDLE;
|
|
node = GetHipadabaNode(self->objectNode,"data");
|
|
assert(node != NULL);
|
|
NotifyHipadabaPar(node,NULL);
|
|
break;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------
|
|
* This handles the terminator discovery and causes the evaluation of complete
|
|
* lines.
|
|
* --------------------------------------------------------------------------*/
|
|
static int LMD200Callback(void *context, int mode){
|
|
pSICSOBJ self = (pSICSOBJ)context;
|
|
pLMD200 priv = NULL;
|
|
char buffer[512], *pPtr = NULL, line[132];
|
|
|
|
assert(self != NULL);
|
|
priv = (pLMD200)self->pPrivate;
|
|
if(mode == nwatch_read){
|
|
memset(buffer,0,512);
|
|
memset(line,0,132);
|
|
NETRead(priv->pSock, buffer, 512, 0);
|
|
pPtr = stptok(buffer,line,132,"\r");
|
|
while(pPtr != NULL){
|
|
if(strlen(line) > 3){
|
|
strncpy(priv->lineBuffer,line,BUFLEN);
|
|
interpretLine(self, priv);
|
|
priv->lineBuffer[0] = '\0';
|
|
}
|
|
pPtr = stptok(pPtr,line,132,"\r");
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int MakeLMD200(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pSICSOBJ self = NULL;
|
|
pLMD200 priv = NULL;
|
|
hdbValue dataValue, textValue;
|
|
int status;
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,
|
|
"ERROR: require name host and port parameters for initialization",
|
|
eError);
|
|
return 0;
|
|
}
|
|
priv = (pLMD200)malloc(sizeof(LMD200));
|
|
memset(priv,0,sizeof(LMD200));
|
|
strncpy(priv->host,argv[2], 256);
|
|
priv->port = atoi(argv[3]);
|
|
priv->pSock = NETConnect(priv->host,priv->port);
|
|
if(priv->pSock == NULL){
|
|
SCWrite(pCon,"ERROR: failed to connect to LMD200",eError);
|
|
killLMD200(priv);
|
|
return 0;
|
|
}
|
|
|
|
self = MakeSICSOBJv(argv[1],"LMD400",HIPNONE, 0);
|
|
if(self == NULL || priv == NULL){
|
|
return 0;
|
|
}
|
|
textValue = MakeHdbText("I do not feel very alarmed");
|
|
dataValue = makeHdbValue(HIPFLOATAR,16);
|
|
AddSICSHdbPar(self->objectNode,"alarm", usInternal,textValue);
|
|
AddSICSHdbPar(self->objectNode,"data", usInternal,dataValue);
|
|
self->pPrivate = priv;
|
|
self->KillPrivate = killLMD200;
|
|
ReleaseHdbValue(&dataValue);
|
|
ReleaseHdbValue(&textValue);
|
|
NetWatchRegisterCallback(&priv->watchContext, priv->pSock->sockid,
|
|
LMD200Callback, self);
|
|
|
|
status = AddCommand(pSics,
|
|
argv[1],
|
|
InterInvokeSICSOBJ,
|
|
KillSICSOBJ,
|
|
self);
|
|
if(status != 1){
|
|
KillSICSOBJ(self);
|
|
SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
|
|
return 1;
|
|
}
|