254 lines
7.1 KiB
C
254 lines
7.1 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
|
|
*
|
|
* modifed to use asynnet and to cope with even more data.
|
|
* Mark Koennecke, June 2009
|
|
*/
|
|
#include <sics.h>
|
|
#include <sicsobj.h>
|
|
#include <sicshipadaba.h>
|
|
#include <asynnet.h>
|
|
#include <stptok.h>
|
|
/*
|
|
* possible states
|
|
*/
|
|
#define IDLE 0
|
|
#define WAITDATA1 1
|
|
#define WAITDATA2 2
|
|
/*
|
|
* private data structure
|
|
*/
|
|
#define BUFLEN 1024
|
|
typedef struct {
|
|
char host[256];
|
|
int port;
|
|
int asChannel;
|
|
char lineBuffer[BUFLEN];
|
|
} LMD200, *pLMD200;
|
|
/*----------------------------------------------------------------------------*/
|
|
static void killLMD200(void *data)
|
|
{
|
|
pLMD200 priv = (pLMD200) data;
|
|
if (priv == NULL) {
|
|
return;
|
|
}
|
|
ANETclose(priv->asChannel);
|
|
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);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static void doAlarm(pSICSOBJ self, char *lineBuffer)
|
|
{
|
|
|
|
setAlarm(self, lineBuffer);
|
|
Log(ERROR,"dev","CERCA:%s ", 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 || strstr(number,"----") != NULL) {
|
|
node->value.v.floatArray[start] = -99.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);
|
|
strlcpy(myBuffer, lineBuffer,BUFLEN);
|
|
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, stamp = NULL;
|
|
hdbValue timeVal;
|
|
|
|
node = GetHipadabaNode(self->objectNode, "data");
|
|
assert(node != NULL);
|
|
|
|
/* printf("Interpreting line: %s\n", priv->lineBuffer); */
|
|
if (strstr(priv->lineBuffer, "Alarm") != NULL) {
|
|
doAlarm(self, priv->lineBuffer);
|
|
return;
|
|
} else if (strstr(priv->lineBuffer, "Pre") != NULL) {
|
|
setAlarm(self, priv->lineBuffer);
|
|
} else if (strstr(priv->lineBuffer, "001...008") != NULL) {
|
|
storeData(self, 0, priv->lineBuffer);
|
|
NotifyHipadabaPar(node, NULL);
|
|
return;
|
|
} else if(strstr(priv->lineBuffer,"009...016") != NULL) {
|
|
storeData(self, 8, priv->lineBuffer);
|
|
NotifyHipadabaPar(node, NULL);
|
|
} else if(strstr(priv->lineBuffer,"017...019") != NULL) {
|
|
storeData(self, 16, priv->lineBuffer);
|
|
NotifyHipadabaPar(node, NULL);
|
|
} else {
|
|
if(strlen(priv->lineBuffer) > 5){
|
|
timeVal = MakeHdbText(priv->lineBuffer);
|
|
stamp = GetHipadabaNode(self->objectNode, "timestamp");
|
|
if(stamp != NULL){
|
|
UpdateHipadabaPar(stamp, timeVal, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int LMD200Callback(int handle, void *userData)
|
|
{
|
|
pSICSOBJ self = (pSICSOBJ)userData;
|
|
pLMD200 priv = (pLMD200)self->pPrivate;
|
|
char *pPtr = NULL, *pEnd = NULL;
|
|
int length;
|
|
|
|
pPtr = ANETreadPtr(priv->asChannel,&length);
|
|
pEnd = strchr(pPtr,(int)'\r');
|
|
while(pEnd != NULL){
|
|
*pEnd = '\0';
|
|
strlcpy(priv->lineBuffer,pPtr,BUFLEN);
|
|
interpretLine(self,priv);
|
|
ANETreadConsume(priv->asChannel,(pEnd - pPtr)+1);
|
|
pPtr = ANETreadPtr(priv->asChannel,&length);
|
|
if(length > 0){
|
|
pEnd = strchr(pPtr,(int)'\r');
|
|
} else {
|
|
pEnd = NULL;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int ClearCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
setAlarm(ccmd,"I do not feel very alarmed...");
|
|
SCSendOK(con);
|
|
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));
|
|
strlcpy(priv->host, argv[2], 256);
|
|
priv->port = atoi(argv[3]);
|
|
priv->asChannel = ANETconnect(priv->host, priv->port);
|
|
if (priv->asChannel < 0) {
|
|
SCWrite(pCon, "ERROR: failed to connect to LMD200", eLogError);
|
|
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, 32);
|
|
AddSICSHdbPar(self->objectNode, "alarm", usInternal, textValue);
|
|
AddSICSHdbPar(self->objectNode, "timestamp", usInternal, textValue);
|
|
AddSICSHdbPar(self->objectNode, "data", usInternal, dataValue);
|
|
self->pPrivate = priv;
|
|
self->KillPrivate = killLMD200;
|
|
ReleaseHdbValue(&dataValue);
|
|
ANETsetReadCallback(priv->asChannel,LMD200Callback,self, NULL);
|
|
|
|
AddSICSHdbPar(self->objectNode,
|
|
"clearalarm", usUser, MakeSICSFunc(ClearCmd));
|
|
|
|
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;
|
|
}
|