1053 lines
27 KiB
C
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 = ∅
|
|
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);
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|