Files
sicspsi/lmd200.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;
}