Files
sicspsi/eve.c
2005-09-02 13:04:49 +00:00

1053 lines
27 KiB
C

/*---------------------------------------------------------------------------
eve.c
extended environment controller utilities
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include <ctype.h>
#include "sics.h"
#include "rs232controller.h"
#include "obpar.h"
#include "evcontroller.h"
#include "evcontroller.i"
#include "evdriver.i"
#include "eve.h"
#include "fsm.h"
#include "logger.h"
#define ILLNUM -1456
#define ILLARGC -1457
#define AMBIGUOS -1458
#define ILLPRIV -1460
#define BADLOG -1461
#define BUSY -1462
typedef enum {
cntAction, iniAction, parAction, listAction,
logAction, logSwitchAction, saveAction
} EveAction;
typedef enum { noOp, fmtOp, setOp } ArgOp;
struct EveParArg {
EveAction action;
int argc;
char **argv;
int ret; /* return value */
SConnection *pCon;
pEVControl evc;
time_t now;
int period;
int idx;
FILE *fil;
};
struct EvePar {
char *name;
Logger *log;
};
/*--------------------------------------------------------------------------*/
char *EveArg2Text(int argc, char *argv[], char *res, int maxsize) {
int i, l;
char *p;
if (res == NULL) {
maxsize = 0;
for (i=0; i<argc; i++) {
maxsize += strlen(argv[i]) + 1;
}
res=malloc(maxsize);
}
maxsize--;
*res='\0';
strncat(res, argv[0], maxsize);
p = res;
for (i=1; i<argc; i++) {
l = strlen(p);
p += l;
maxsize -= l;
if (maxsize == 0) return res;
*p=' ';
p++;
maxsize--;
*p='\0';
strncat(p, argv[i], maxsize);
}
return res;
}
/*--------------------------------------------------------------------------*/
int EvePrintf(Eve *eve, int iOut, char *fmt, ...) {
va_list ap;
char buf[1024];
SConnection *pCon;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
eve->errMsg[0] = '\0';
if (eve->evc != NULL) {
pCon = SCLoad(&eve->evc->conn);
if (pCon != NULL) {
if (iOut < 0) {
if (-iOut > eve->verbose) return 0;
iOut=eStatus;
}
return SCWrite(pCon, buf, iOut);
}
}
if (iOut == eError) {
snprintf(eve->errMsg, sizeof eve->errMsg, "%s", buf);
}
return 1;
}
/*--------------------------------------------------------------------------*/
int EveText2Int(char *list[], char *text) {
int num = 0;
char *endp;
while (list[num] != NULL) {
if (strcasecmp(list[num],text) == 0) {
return num;
}
num++;
}
num = strtol(text, &endp, 0);
if (endp == text) return -1;
return num;
}
/*--------------------------------------------------------------------------*/
char *EveInt2Text(char *list[], int num) {
int i;
static char buf[12];
for (i = 0; i <= num; i++) {
if (list[i] == NULL) {
snprintf(buf, sizeof buf, "%d", num);
return buf;
}
}
return list[num];
}
/*----------------------------------------------------------------------------*/
int EveCheckRights(EveParArg *arg, int access) {
if (SCMatchRights(arg->pCon,access)) {
return 1;
} else {
arg->ret = ILLPRIV;
}
return 0;
}
/*--------------------------------------------------------------------------*/
void EveMakePar(Eve *eve) {
EveParArg arg;
int i;
if (eve->par == NULL) {
arg.action = cntAction;
arg.pCon = NULL;
arg.evc = eve->evc;
arg.idx = 0;
eve->pardef(eve, &arg); /* first time: count */
eve->npar = arg.idx;
eve->par = calloc(arg.idx, sizeof *eve->par);
for (i=0; i<arg.idx; i++) {
eve->par[i].log = NULL;
eve->par[i].name = NULL;
}
arg.action = iniAction;
arg.idx = 0;
eve->pardef(eve, &arg); /* second time: start default loggers */
}
}
/*--------------------------------------------------------------------------*/
void EveLog(Eve *eve) {
EveParArg arg;
if (!eve->par) {
EveMakePar(eve);
}
arg.now = time(NULL);
if (arg.now >= (eve->logtime / eve->period + 1) * eve->period) {
arg.action = logAction;
arg.pCon = NULL;
arg.evc = eve->evc;
arg.argc = 0;
arg.idx = 0;
arg.period = eve->period;
eve->pardef(eve, &arg);
eve->logtime = arg.now;
}
}
/*----------------------------------------------------------------------------*/
int EveSwitchLog(Eve *eve, EvePar *par, int on) {
char buf[80];
if (on) {
if (par->log == NULL) {
if (par->name[0] == '\0') {
par->log = LoggerMake(eve->evc->pName, eve->period, 0);
} else {
snprintf(buf, sizeof buf, "%s.%s", eve->evc->pName, par->name);
par->log = LoggerMake(buf, eve->period, 0);
}
if (par->log == NULL) {
return BADLOG;
}
}
} else {
if (par->log != NULL) {
LoggerKill(par->log);
par->log = NULL;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
EvePar *EveThisPar(EveParArg *arg, char *name, int flags) {
Eve *eve = arg->evc->pDriv->pPrivate;
EvePar *par;
if (!eve->par) return NULL;
assert(arg->idx < eve->npar);
par = eve->par + arg->idx;
if (par->name == NULL) {
par->name = name;
if (flags & EVE_LOGPAR) { /* first time: default logger */
EveSwitchLog(eve, par, 1);
}
} else {
assert(par->name == name);
}
return par;
}
/*----------------------------------------------------------------------------*/
ArgOp EveOp(EveParArg *arg, char *name, char **fmt, int access, int flags) {
static char buf[80];
char *sp;
int l;
EvePar *par;
ArgOp op;
switch (arg->action) {
case cntAction:
arg->idx ++;
return noOp;
case iniAction:
EveThisPar(arg, name, flags);
arg->idx ++;
return noOp;
case listAction:
if (flags & EVE_ACTPAR) {
return fmtOp;
}
return noOp;
case logAction:
if (flags & EVE_ACTPAR) {
op = fmtOp;
break; /* reduce fmt */
}
arg->idx++;
return noOp;
case logSwitchAction:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return noOp;
}
if (0==strcasecmp(name, arg->argv[1])) {
if (arg->ret) {
arg->ret = AMBIGUOS;
return noOp;
}
par = EveThisPar(arg, name, 0);
EveSwitchLog(arg->evc->pDriv->pPrivate, par, toupper(arg->argv[0][0]) == 'L');
}
arg->idx ++;
return noOp;
case parAction:
if (0==strcasecmp(name, arg->argv[0])) {
if (arg->ret) {
arg->ret = AMBIGUOS;
return noOp;
}
arg->ret = 1;
if (arg->argc == 1) {
op = fmtOp;
break; /* reduce fmt */
}
if (!EveCheckRights(arg, access)) return noOp;
op = setOp;
break;
}
return noOp;
case saveAction:
if (flags & EVE_SAVEPAR) {
op = fmtOp;
break; /* reduce fmt */
}
return noOp;
default:
return noOp;
}
if (fmt != NULL) {
/* skip fmt after tab */
sp = strchr(*fmt, '\t');
if (sp != NULL) {
l = sp - *fmt;
if (l >= sizeof buf) l = sizeof buf - 1;
strncpy(buf, *fmt, l);
buf[l]='\0';
*fmt = buf;
}
}
return op;
}
/*----------------------------------------------------------------------------*/
void EveOut(EveParArg *arg, char *name, char *buf) {
EvePar *par;
int l, i, j, m, ln, lp, iret;
char *p, *q, *tab;
char buffer[256];
char *dot;
switch (arg->action) {
case listAction:
p = buf;
while (*p == ' ') p++; /* skip blanks */
i = 0;
if (p[i] == '-') i++;
j = i;
while (p[i] >= '0' && p[i] <='9') i++;
tab = strchr(p, '\t');
if (tab) {
l = tab - p;
*tab = ' ';
} else {
l = strlen(p);
}
ln = strlen(name);
if (i != j && (buf[i] == '.' || buf[i] <= ' ')) {
l += 16 - i - ln; /* decimal point or end of number at least 16 chars after object name */
if (tab) {
*tab = '\0';
q = tab + 1;
} else {
q = "";
}
lp = strlen(p);
if (l < lp) l = lp;
m = 22 - l - ln; /* unit/comment at least 22 chars after object name */
if (m < 1) m = 1;
m += strlen(q);
} else {
l = 16 - ln;
q = "";
m = 0;
}
if (l <= 0) l = 1;
SCPrintf(arg->pCon, eStatus, "%s %s %*s%*s", arg->evc->pName, name, l, p, m, q);
break;
case parAction:
SCPrintf(arg->pCon, eValue, "%s %s = %s", arg->evc->pName, name, buf);
break;
case logAction:
par = EveThisPar(arg, name, 0);
arg->idx ++;
if (par->log) {
iret = LoggerWrite(par->log, arg->now, arg->period, buf);
if (iret) {
if (*name) {
dot = ".";
} else {
dot = "";
}
snprintf(buffer, sizeof buffer, "%s%s%s = %s", arg->evc->pName, dot, name, buf);
InvokeCallBack(arg->evc->pCall, VALUECHANGE, buffer);
}
}
break;
case saveAction:
fprintf(arg->fil, "%s %s %s\n", arg->evc->pName, name, buf);
break;
default: break;
}
}
/*----------------------------------------------------------------------------*/
void EveFloatPar(EveParArg *arg, char *name, float *value, char *fmt,
int access, int flags) {
char *endp;
float f;
char buf[132];
switch (EveOp(arg, name, &fmt, access, flags)) {
case setOp:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return;
}
f = strtod(arg->argv[1], &endp);
if (endp == arg->argv[1]) {
arg->ret = ILLNUM;
break;
}
*value = f;
SCparChange(arg->pCon);
/* fall through */
case fmtOp:
snprintf(buf, sizeof buf, fmt, *value);
EveOut(arg, name, buf);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveIntPar(EveParArg *arg, char *name, int *value, int access, int flags) {
char *endp;
int i;
char buf[132];
switch (EveOp(arg, name, NULL, access, flags)) {
case setOp:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return;
}
i = strtol(arg->argv[1], &endp, 0);
if (endp == arg->argv[1]) {
arg->ret = ILLNUM;
break;
}
*value = i;
SCparChange(arg->pCon);
/* fall through */
case fmtOp:
snprintf(buf, sizeof buf, "%d", *value);
EveOut(arg, name, buf);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveStrPar(EveParArg *arg, char *name, char **value, int maxsize, int access, int flags) {
static char *empty="";
switch (EveOp(arg, name, NULL, access, flags)) {
case setOp:
if (maxsize == 0) { /* dynamic string */
if (*value != NULL) free(*value);
*value = EveArg2Text(arg->argc-1, arg->argv+1, NULL, 0);
} else { /* fixed string */
EveArg2Text(arg->argc, arg->argv, *value, maxsize);
}
SCparChange(arg->pCon);
/* fall through */
case fmtOp:
if (*value == NULL) value = &empty;
EveOut(arg, name, *value);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveObPar(EveParArg *arg, int index, char *fmt, int flags) {
char *name;
char *endp;
char buf[132];
float f;
name = arg->evc->pParam[index].name;
switch (EveOp(arg, name, &fmt, arg->evc->pParam[index].iCode, flags)) {
case setOp:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return;
}
f = strtod(arg->argv[1], &endp);
if (endp == arg->argv[1]) {
arg->ret = ILLNUM;
} else {
arg->evc->pParam[index].fVal = f;
}
SCparChange(arg->pCon);
/* fall through */
case fmtOp:
snprintf(buf, sizeof buf, fmt, arg->evc->pParam[index].fVal);
EveOut(arg, name, buf);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveObParEnum(EveParArg *arg, int index, char *list[], int flags) {
char *name;
int i;
char buf[132];
char *fmt="%d\t(%s)";
name=arg->evc->pParam[index].name;
switch (EveOp(arg, name, &fmt, arg->evc->pParam[index].iCode, flags)) {
case setOp:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return;
}
i = EveText2Int(list, arg->argv[1]);
if (i<0) {
arg->ret = ILLNUM;
} else {
arg->evc->pParam[index].fVal = i;
}
SCparChange(arg->pCon);
/* fall through */
case fmtOp:
i = (int)ObVal(arg->evc->pParam, index);
snprintf(buf, sizeof buf, fmt, i, EveInt2Text(list, i));
EveOut(arg, name, buf);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveEnumPar(EveParArg *arg, char *name, int *value, char *list[], int access, int flags) {
int i;
char buf[132];
char *fmt="%d\t(%s)";
switch (EveOp(arg, name, &fmt, access, flags)) {
case setOp:
if (arg->argc > 2) {
arg->ret = ILLARGC;
return;
}
i = EveText2Int(list, arg->argv[1]);
if (i<0) {
arg->ret = ILLNUM;
} else {
*value = i;
SCparChange(arg->pCon);
}
/* fall through */
case fmtOp:
snprintf(buf, sizeof buf, fmt, *value, EveInt2Text(list, *value));
EveOut(arg, name, buf);
break;
case noOp: break;
}
}
/*----------------------------------------------------------------------------*/
void EveCmd(EveParArg *arg, char *name, EveSubCmd subcmd, int access) {
if (arg->action == parAction) {
if (0==strcasecmp(name, arg->argv[0])) {
if (arg->ret) {
arg->ret = AMBIGUOS;
return;
}
if (!EveCheckRights(arg, access)) return;
arg->ret=subcmd(arg->pCon, arg->evc, arg->argc, arg->argv);
}
}
}
/*----------------------------------------------------------------------------*/
void EveFloatCmd(EveParArg *arg, char *name, float *value, char *fmt,
FsmFunc fsmFunc, int access, int flags) {
Eve *eve;
EveFloatPar(arg, name, value, fmt, access, flags);
if (arg->action == parAction && arg->argc == 2 && 0==strcasecmp(name, arg->argv[0])) {
eve = (Eve *)arg->evc->pDriv->pPrivate;
if (eve->todo) {
arg->ret = BUSY;
} else {
eve->todo = fsmFunc;
}
}
}
/*----------------------------------------------------------------------------*/
#define A EVE_ACTPAR
#define L EVE_LOGPAR
#define S EVE_SAVEPAR
void EveStdPar(EveParArg *arg) {
static char *errList[]={"noop", "pause", "interrupt", "safeValue", "script", NULL };
static char *intList[]={"continue", "abortOp", "abortScan", "abortBatch", NULL };
float value;
int eh;
EveObPar(arg, UPLIMIT, "%.5g\tK", A + S);
EveObPar(arg, LOWLIMIT, "%.5g\tK", A + S);
EveObPar(arg, TOLERANCE, "%.5g\tK", A + S);
EveObParEnum(arg, ERRORHANDLER, errList, A + S);
eh = (int)ObVal(arg->evc->pParam, ERRORHANDLER);
EveObParEnum(arg, INTERRUPT, intList, (eh == 2) * A + S);
EveObPar(arg, SAFEVALUE, "%.5g\tK", (eh == 3) * A + S);
EveStrPar(arg, "errorScript", &arg->evc->errorScript, 0, usUser, (eh == 4) * A + S);
EveObPar(arg, MAXWAIT, "%.0f\tsec", A + S);
EveObPar(arg, SETTLE, "%.0f\tsec", A + S);
}
/*----------------------------------------------------------------------------*/
void EveStdParEnd(EveParArg *arg, char *fmt, int targetFlag) {
static char *accessList[]={"internal", "manager", "user", "spy", NULL };
float value;
pEVControl evc = arg->evc;
Eve *eve = evc->pDriv->pPrivate;
EveIntPar(arg, "verbose", &eve->verbose, usUser, S);
EveIntPar(arg, "period", &eve->period, usUser, S);
EveObParEnum(arg, ACCESS, accessList, A+S);
EveStrPar(arg, "driver", &evc->driverName, 0, usInternal, A);
EveFloatPar(arg, "targetValue", &evc->fTarget, fmt, usInternal, targetFlag);
EveFloatPar(arg, "", &eve->value, fmt, usInternal, A+L);
}
/*----------------------------------------------------------------------------*/
SConnection *EveArgConn(EveParArg *arg) {
return arg->pCon;
}
/*----------------------------------------------------------------------------*/
int EveUserAction(EveParArg *arg) {
return (arg->action == parAction || arg->action == listAction);
}
/*----------------------------------------------------------------------------*/
int EveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]) {
pEVControl evc = pData;
EveParArg arg;
Eve *eve = evc->pDriv->pPrivate;
if (eve->state == lostState) {
SCPrintf(pCon, eError, "%s does not respond", evc->pDes->name);
return -1;
}
arg.pCon = pCon;
arg.evc = evc;
arg.ret = 0;
if (argc == 2 && 0==strcasecmp(argv[1], "list")) {
arg.action = listAction;
eve->pardef(evc->pDriv->pPrivate, &arg);
return 1;
}
if (argc == 3 && (0 == strcasecmp(argv[1], "log")
|| 0 == strcasecmp(argv[1], "unlog"))) {
if (!eve->par) EveMakePar(eve);
arg.action = logSwitchAction;
arg.argc = argc - 1;
arg.argv = argv + 1;
arg.idx = 0;
eve->pardef(eve, &arg);
} else {
arg.action = parAction;
arg.argc = argc - 1;
arg.argv = argv + 1;
if (argc > 1) eve->pardef(eve, &arg);
if (arg.ret == 0) { /* forward to standard EVController */
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
}
error:
switch (arg.ret) {
case AMBIGUOS:
SCPrintf(pCon, eError, "ERROR: doubly defined parameter %s.%s", evc->pName, argv[1]);
break;
case ILLPRIV:
SCPrintf(pCon, eError, "ERROR: Insufficient privilege to change %s.%s", evc->pName, argv[1]);
break;
case ILLNUM:
SCPrintf(pCon, eError, "ERROR: illegal value", evc->pName, argv[2]);
break;
case ILLARGC:
SCPrintf(pCon, eError, "ERROR: illegal number of arguments for %s %s", evc->pName, argv[1]);
break;
case BADLOG:
SCPrintf(pCon, eError, "ERROR: can not create log directory for %s %s", evc->pName, argv[1]);
break;
case BUSY:
SCPrintf(pCon, eError, "ERROR: %s busy", evc->pName);
break;
default:
return arg.ret;
}
return -1;
}
/*----------------------------------------------------------------------------*/
void EveWriteError(Eve *eve) {
switch (eve->errCode) {
case NOTCONNECTED:
EvePrintf(eve, eError, "terminalserver for %s not connected", eve->evc->pName);
break;
case FAILEDCONNECT:
EvePrintf(eve, eError, "can not connect to %s:%d", eve->ser->pHost, eve->ser->iPort);
break;
case TIMEOUT:
EvePrintf(eve, eError, "timeout on %s", eve->evc->pName);
break;
case INCOMPLETE:
EvePrintf(eve, eError, "incomplete answer %s from %s", eve->ans, eve->evc->pName);
break;
case EVE_ILL_ANS:
EvePrintf(eve, eError, "illegal answer %s from %s (cmd: %*s)",
eve->ans, eve->evc->pName, strlen(eve->cmd)-1, eve->cmd);
break;
case EVE_DEV_CHANGED:
EvePrintf(eve, eError, "controller was exchanged on %s", eve->evc->pName);
break;
case EVE_FAULT:
EvePrintf(eve, eError, "error on %s", eve->evc->pName);
break;
default:
EvePrintf(eve, eError, "error code %d on %s", eve->errCode, eve->evc->pName);
break;
}
}
/*----------------------------------------------------------------------------*/
void EveWrite(Eve *eve, char *cmd) {
int iRet;
char trash[64];
int l, iret;
if (eve->errCode || eve->state == expectState) return;
while (availableRS232(eve->ser) == 1) {
l=sizeof(trash);
iret = readRS232TillTerm(eve->ser, trash, &l);
EvePrintf(eve, -2, "trash: %s\n", trash);
}
snprintf(eve->cmd, sizeof(eve->cmd), "%s\n", cmd);
iRet = writeRS232(eve->ser, eve->cmd, strlen(eve->cmd));
EvePrintf(eve, -2, "cmd: %s", cmd);
eve->state = expectState;
eve->cmdtime = time(NULL);
}
/*----------------------------------------------------------------------------*/
void EveWaitRead(Eve *eve) {
int cnt=0;
FsmPause(eve->task, 1);
while (eve->state == expectState) {
TaskYield(pServ->pTasker); /* wait for handling the last message */
cnt++;
}
FsmPause(eve->task, 0);
/* if (cnt>1) printf("TaskYield %d\n", cnt); */
}
/*----------------------------------------------------------------------------*/
int EveHandler(Eve *eve) {
if (eve->state == expectState) return 0;
if (eve->errCode) {
eve->hwstate = HWFault;
EveWriteError(eve);
eve->errCode = 0;
FsmStop(eve->task, eve->run);
return 0;
}
if (eve->state == lostState) {
if (FsmStop(eve->task, eve->run)) {
EvePrintf(eve, -1, "stop %s caused by timeout", eve->evc->pName);
}
return 0;
}
if (eve->evc->iStop && eve->hwstate == HWBusy) {
if (FsmStop(eve->task, eve->run)) {
EvePrintf(eve, -1, "%s stopped", eve->evc->pName);
return 0;
}
}
return 1;
}
/*----------------------------------------------------------------------------*/
int EveIdle(long pc, Eve *eve) {
FsmFunc todo;
struct timeval tm;
FSM_BEGIN
idle:
if (!eve->todo) {
if (eve->hwstate == HWBusy) {
eve->hwstate = HWIdle;
}
goto rd;
}
doit:
todo = eve->todo;
eve->todo = NULL;
FSM_CALL(todo);
rd:
FSM_CALL(eve->read);
EveLog(eve); /* just for the case EveLog was not included in the read function */
if (eve->logtime == 0) eve->logtime = 1;
if (eve->todo) goto doit;
/*
gettimeofday(&tm, NULL);
printf("stop %s %f\n", eve->evc->pName, tm.tv_usec / 1e6);
*/
FSM_WAIT(1)
/*
gettimeofday(&tm, NULL);
printf("start %s %f\n", eve->evc->pName, tm.tv_usec / 1e6);
*/
goto idle;
/* never return */
FSM_END
}
/*----------------------------------------------------------------------------*/
static int EveGet(pEVDriver driver, float *fPos) {
Eve *eve = driver->pPrivate;
assert(driver);
assert(eve);
*fPos=eve->value;
return 1;
}
/*----------------------------------------------------------------------------*/
int EveRun(pEVDriver driver, float fVal) {
Eve *eve = driver->pPrivate;
assert(driver && eve);
if (! eve->run) {
EvePrintf(eve, -1, "can not run %s", eve->evc->pName);
return 0;
}
eve->todo = eve->run;
if (FsmStop(eve->task, eve->run)) {
EvePrintf(eve, -1, "running %s cancelled", eve->evc->pName);
}
eve->hwstate = HWBusy;
return 1;
}
/*--------------------------------------------------------------------------*/
int EveSend(pEVDriver driver, char *pCommand, char *pReply, int iLen) {
Eve *eve = driver->pPrivate;
int iRet;
assert(driver && eve);
EveWaitRead(eve);
if (eve->errCode) {
EveWriteError(eve);
return 0;
}
EvePrintf(eve, -2, "cmd: %s", pCommand);
iRet = transactRS232(eve->ser, pCommand, strlen(pCommand), pReply, iLen);
EvePrintf(eve, -2, "ans: %s", pReply);
if(iRet < 0)
{
eve->errCode = iRet;
EveWriteError(eve);
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int EveCheckStatus(void *evcVoid, SConnection *pCon) {
pEVControl evc=evcVoid;
pEVDriver driver;
Eve *eve;
SConnection *con;
assert(evc);
driver = evc->pDriv;
assert(driver);
eve = driver->pPrivate;
con = SCLoad(&evc->conn);
if (con != pCon) { /* not sure if this is the case in any situation */
if (con) {
SCWrite(con, "no more infos", eWarning);
}
SCWrite(pCon, "infos now here", eWarning);
SCSave(&evc->conn, pCon);
}
return eve->hwstate;
}
/*-------------------------------------------------------------------------*/
EVMode EveGetMode(void *data) {
/* EveGetMode is called in the SICS task loop as long as evc lives
and is not been explicitely unregistered */
pEVControl evc = data;
pEVDriver driver;
Eve *eve = evc->pDriv->pPrivate;
if (eve->task != NULL) {
FsmTaskHandler(eve->task);
}
return evc->eMode;
}
/*-------------------------------------------------------------------------*/
int EveClose(pEVDriver driver) {
/* empty routine */
return 1;
}
/*-------------------------------------------------------------------------*/
int EveAlwaysOk(void *data) {
return 1;
}
/*-------------------------------------------------------------------------*/
int EveDontFix(pEVDriver driver, int iError) {
return(DEVFAULT); /* severe */
}
/*-------------------------------------------------------------------------*/
int EveSavePars(pEVDriver driver, FILE *fil)
{
Eve *eve = driver->pPrivate;
EveParArg arg;
arg.action = saveAction;
arg.pCon = NULL;
arg.evc = eve->evc;
arg.fil = fil;
eve->pardef(eve, &arg);
return 2; /* no (duplicate) save of standard parameters ! */
}
/*-------------------------------------------------------------------------*/
void EveKill(void *pData) {
Eve *eve = pData;
EvePar *p;
Logger *log;
int i;
assert(eve);
KillRS232(eve->ser);
for (i=0; i<eve->npar; i++) {
if (eve->par[i].log) {
LoggerKill(eve->par[i].log);
}
eve->par[i].log = NULL;
}
free(eve);
}
/*--------------------------------------------------------------------------*/
int EveGetError(pEVDriver driver, int *iCode, char *error, int iErrLen) {
Eve *eve = driver->pPrivate;
*iCode = 1; /* severe */
strncpy(error, eve->errMsg, iErrLen);
error[iErrLen-1]='\0';
eve->errMsg[0]='\0';
return 1;
}
/*----------------------------------------------------------------------------*/
int EveInit(pEVDriver driver) {
Eve *eve;
int iRet;
char *res, buf[128];
pExeList exe;
assert(driver);
eve = driver->pPrivate;
eve->errCode = 0;
eve->state = idleState;
eve->version[0] = '\0';
eve->errMsg[0]='\0';
iRet = initRS232(eve->ser);
if (iRet != 1) {
eve->errCode = iRet;
EveWriteError(eve);
return -1;
}
setRS232ReplyTerminator(eve->ser,"\r");
setRS232SendTerminator(eve->ser,"\r");
setRS232Timeout(eve->ser,1000); /* milliseconds */
setRS232Debug(eve->ser,0);
return 1;
}
/*----------------------------------------------------------------------------*/
pEVControl MakeEveEVC(int argc, char *argv[], Eve *eve, SConnection *pCon) {
/* args:
<objectname> <driver> <rs232>
<host> <port>
*/
pEVDriver driver = NULL;
int port;
rs232 *ser;
pEVControl evc;
if (argc < 3 || argc > 4) {
SCWrite(pCon, "illegal number of arguments", eError);
goto error;
}
driver = CreateEVDriver(0,NULL); /* arguments obsolete */
if(!driver || !eve) {
SCWrite(pCon, "ERROR: out of memory", eError);
goto error;
}
driver->pPrivate = eve;
driver->KillPrivate = EveKill;
/* initalise IpsDriver */
eve->evc = NULL;
eve->hwstate = HWIdle;
eve->task = NULL;
eve->run = NULL;
eve->logtime = 0;
eve->period = 5;
eve->par = NULL;
if (argc == 4) {
port=atoi(argv[3]);
if (port==0) {
SCWrite(pCon, "ERROR: illegal port number", eError);
goto error;
}
ser = createRS232(argv[2], port);
if (ser == NULL) {
SCWrite(pCon, "out of memory", eError);
goto error;
}
} else {
ser = FindCommandData(pServ->pSics, argv[2], "RS232 Controller");
if (ser == NULL) {
SCWrite(pCon, "ERROR: rs232 not found", eError);
goto error;
}
}
eve->ser = ser;
/* initialise function pointers */
driver->GetValue = EveGet;
driver->SetValue = EveRun;
driver->Send = EveSend;
driver->GetError = EveGetError;
driver->TryFixIt = EveDontFix;
driver->SavePars = EveSavePars;
driver->Init = EveInit;
driver->Close = EveClose;
evc = MakeEVController(driver, pCon, EveWrapper, argc, argv);
if (!evc) return NULL;
eve->evc=evc;
eve->hwstate = HWIdle;
eve->verbose = 1;
SCSave(&eve->evc->conn, pCon);
eve->checkStatus = evc->pDrivInt->CheckStatus;
evc->pDrivInt->CheckStatus = EveCheckStatus;
evc->pEnvir->GetMode = EveGetMode;
return evc;
error:
if (driver) {
free(driver);
driver = NULL;
}
/* write out error message */
return MakeEVController(driver, pCon, EveWrapper, argc, argv);
}
/*----------------------------------------------------------------------------*/