improvements:

- added is_running to driveable ease objects
- ighdriv.c: try <maxtry> times when status reply failes
- ipsdriv.c: fix trainedTo parameter
- reduced SEA version of SICS
This commit is contained in:
2021-09-16 12:35:06 +02:00
parent 21299efa80
commit f16d738b4a
10 changed files with 607 additions and 80 deletions

View File

@ -164,6 +164,7 @@ static int ArrayMakeItem(void *object, void *delete, int argc,
*last = item->next; /* remove item from list */
item->next = arr->freeItems;
arr->freeItems = item;
ParKillPar(arr, item->name);
return 1;
}
break;
@ -230,7 +231,7 @@ static int ArrayMakeItem(void *object, void *delete, int argc,
item->unit = strdup(item->unit);
if (item->value)
item->value = strdup(item->value);
ParInitPar(object, item->name);
ParInitPar(object, item->name, arr->logged);
SCparChange(arr->p.conn);
return 1;
@ -318,6 +319,7 @@ static void ArrayObjParDef(void *object)
if (ParActionIs(PAR_KILL)) {
for (item = arr->items; item != NULL; item = next) {
next = item->next;
ParKillPar(arr, item->name);
if (item->name)
free(item->name);
if (item->unit)
@ -350,7 +352,7 @@ static int ArrayObjInit(SConnection * con, int argc, char *argv[],
creationCmd = Arg2Tcl(argc, argv, NULL, 0);
}
arr = ParMake(con, argv[1], &arrayObjClass, ArrayObjParDef, creationCmd);
if (argc > 2 && strcasecmp(argv[2], "logged") == 0) {
if (argc > 3 && strcasecmp(argv[3], "logged") == 0) {
arr->logged = 1;
} else {
arr->logged = 0;

46
ease.c
View File

@ -19,6 +19,7 @@ Markus Zolliker, March 2005
#include "sics.h"
#include "splitter.h"
#include "ease.h"
#include "sicshipadaba.h"
#define EASE_FLAGBITS (8*sizeof(long))
@ -242,16 +243,29 @@ static int EaseRestart(EaseBase * eab)
return 0;
}
/*----------------------------------------------------------------------------*/
void EaseUpdateHwstate(void *object, int drivStatus) {
EaseDriv *ead = EaseDrivCast(object);
int is_running = drivStatus == HWBusy;
ead->hwstate = drivStatus;
if (ead->is_running != is_running) {
ead->is_running = is_running;
ParUpdateAll(ead);
}
}
/*----------------------------------------------------------------------------*/
int EaseHandler(EaseBase * eab)
{
EaseDriv *ead = EaseDrivCast(eab);;
EaseDriv *ead = EaseDrivCast(eab);
int iret;
EaseSavePars();
if (ead && ead->stopped && ead->hwstate == HWBusy) {
ead->stopped = 0;
ead->hwstate = HWIdle;
EaseUpdateHwstate(ead, HWIdle);
if (FsmStop(eab->task, eab->doit)) {
ParPrintf(eab, eWarning, "%s stopped", eab->p.name);
return 0;
@ -314,7 +328,7 @@ int EaseHandler(EaseBase * eab)
}
eab->errCode = 0;
if (ead) {
ead->hwstate = HWFault;
EaseUpdateHwstate(ead, HWFault);
FsmStop(eab->task, eab->doit);
}
return 0;
@ -563,7 +577,8 @@ static long EaseRun(void *obj, SConnection * pCon, float fVal)
ead->stopped = 0;
/* eab->todo = eab->doit; */
EaseSetUpdate(eab, EASE_RUN, 1);
ead->hwstate = HWBusy;
ead->is_running = -1; /* force update of is_running even when not changed */
EaseUpdateHwstate(ead, HWBusy);
if (ead->maxwait >= 0) {
ead->timeout = time(NULL) + ead->maxwait;
} else {
@ -633,12 +648,15 @@ static int EaseCheckStatus(void *obj, SConnection * pCon)
ParSaveConn(ead, pCon);
if (ead->stopped) {
return HWIdle;
} else if (!ead->is_running) {
ead->stopped = 1;
return HWIdle;
}
now = time(NULL);
if (now > ead->timeout) {
ParPrintf(obj, eWarning, "maxwait expired when driving %s",
ead->b.p.name);
ead->hwstate = HWIdle;
EaseUpdateHwstate(ead, HWIdle);
} else if (EaseIsInTol(obj)) {
if (ead->finish == 0) {
ead->finish = now - ead->usedSettle;
@ -649,7 +667,7 @@ static int EaseCheckStatus(void *obj, SConnection * pCon)
}
if (now > ead->finish + ead->settle && ead->hwstate != HWIdle) {
ParPrintf(obj, eWarning, "%s has reached target", ead->b.p.name);
ead->hwstate = HWIdle;
EaseUpdateHwstate(ead, HWIdle);
}
} else if (ead->finish != 0) {
ead->usedSettle = now - ead->finish;
@ -930,7 +948,6 @@ void *EaseMakeDriv(SConnection * con, void *class, int argc, char *argv[],
ead->evInt->IsInTolerance = EaseIsInTol;
ead->evInt->HandleError = EaseErrHandler;
ead->hwstate = HWIdle;
ead->drivInt->Halt = EaseHalt;
ead->drivInt->CheckLimits = EaseCheckLimits;
ead->drivInt->SetValue = EaseRun;
@ -943,7 +960,9 @@ void *EaseMakeDriv(SConnection * con, void *class, int argc, char *argv[],
ead->settle = 0;
ead->tolerance = 1;
ead->targetValue = 0;
ead->is_running = 0;
EaseUpdateHwstate(ead, HWIdle);
/* EMon interface to be implemented */
return ead;
}
@ -1113,6 +1132,17 @@ void EaseKillDriv(EaseDriv * ead)
}
}
/*----------------------------------------------------------------------------*/
void EaseRunPar(void *object)
{
EaseDriv *ead;
assert(ead = EaseDrivCast(object));
ParName("is_running");
ParInt(&ead->is_running, 0);
}
/*----------------------------------------------------------------------------*/
void EaseDrivPar(void *object, char *fmt, char *unit)
{
@ -1164,6 +1194,8 @@ void EaseDrivPar(void *object, char *fmt, char *unit)
ParTail(unit);
ParFloat(&ead->targetValue, PAR_NAN);
EaseRunPar(ead);
if (ParActionIs(PAR_KILL)) {
EaseKillDriv(ead);
}

3
ease.h
View File

@ -71,6 +71,7 @@ typedef struct {
float targetValue;
time_t timeout, finish;
int usedSettle;
int is_running;
} EaseDriv;
ParClass *EaseBaseClass(void);
@ -87,6 +88,7 @@ void EaseBasePar(void *object);
void EaseSendPar(void *object);
void EaseMsgPar(void *object);
void EaseKillDriv(EaseDriv * ead);
void EaseRunPar(void *object); /* is_running parameter */
void EaseDrivPar(void *object, char *fmt, char *unit);
void EasePchk(void *drv);
void EaseParHasChanged(void);
@ -112,6 +114,7 @@ int EaseGetUpdate(void *object, int flag);
void EaseSetUpdate(void *object, int flag, int state);
/* set an update flag */
void EaseUpdateHwstate(void *object, int drivStatus);
void *EaseMakeBase(SConnection * con, void *class, int argc, char *argv[],
int dynamic, int maxflag,
ParDef pardef,

View File

@ -148,7 +148,7 @@ static int Euro2kMakePar(void *object, void *userarg, int argc,
par->unit = strdup(par->unit);
if (par->fmt)
par->fmt = strdup(par->fmt);
ParInitPar(object, par->name);
ParInitPar(object, par->name, 1);
EaseParHasChanged();
drv->readPar = NULL;
return 1;

View File

@ -89,6 +89,10 @@ typedef struct {
int pumpoff; /* pump signal after overpressure switch */
float upperN2; /* LN2 trap sensor */
float lowerN2;
char lastans[64];
int badcnt;
int maxtry;
int pumpoffcnt;
} Igh;
static ParClass ighClass = { "IGH", sizeof(Igh) };
@ -308,6 +312,11 @@ static void IghParDef(void *object)
if (drv->extVersion != 0) ParTail("K");
ParFloat(&drv->lowerN2, PAR_NAN);
ParName("maxtry");
ParAccess(usUser);
ParSave(1);
ParInt(&drv->maxtry, 0);
EaseBasePar(drv);
EaseSendPar(drv);
if (eab->syntax != OLDIGH) {
@ -318,7 +327,7 @@ static void IghParDef(void *object)
}
/*----------------------------------------------------------------------------*/
void IghStatus(Igh * drv)
int IghStatus(Igh * drv)
{
char *ans;
int *code;
@ -326,7 +335,7 @@ void IghStatus(Igh * drv)
int i;
if (drv->d.b.state != EASE_read)
return;
return 1;
if (drv->opentime > 0 &&
DoubleTime() > drv->opentime + (double)drv->closedelay - 1) {
@ -334,22 +343,46 @@ void IghStatus(Igh * drv)
drv->d.b.todo = drv->d.b.doit;
}
ans = drv->d.b.ans;
code = &drv->d.b.errCode;
ans = drv->d.b.ans;
if (drv->maxtry > 0 && strcmp(ans, drv->lastans) != 0) {
strlcpy(drv->lastans, ans, sizeof(drv->lastans));
drv->badcnt++;
if (drv->badcnt >= drv->maxtry) {
drv->badcnt = 0;
ParPrintf(drv, eError, "inconsistent status response: %s", ans);
*code = EASE_FAULT;
return 1;
}
return 0; /* try again */
}
strlcpy(drv->lastans, ans, sizeof(drv->lastans));
if (ans[0] != 'X' ||
ans[2] != 'A' ||
ans[4] != 'C' ||
ans[6] != 'P' ||
ans[15] != 'S' || ans[17] != 'O' || ans[19] != 'E') {
ParPrintf(drv, eError, "illegal status response: %s", ans);
drv->badcnt++;
if (drv->badcnt < drv->maxtry) {
return 0; /* try again */
}
ParPrintf(drv, eError, "illegal status response (dil maxtry 10 might help): %s", ans);
*code = EASE_FAULT;
return;
return 1;
}
if (sscanf(ans + 7, "%lx", &mask) <= 0) {
drv->badcnt++;
if (drv->badcnt < drv->maxtry) {
return 0; /* try again */
}
ParPrintf(drv, eError, "illegal valve status response");
*code = EASE_FAULT;
return;
return 1;
}
if (drv->badcnt > drv->maxtry / 2) {
ParPrintf(drv, eError, "needed %d retries for getting dil status", drv->badcnt);
}
drv->badcnt = 0;
p = 1;
for (i = 0; i < n_VALVES; i++) {
if (!EaseGetUpdate(drv, VALVE_FLAGS + i)) {
@ -376,9 +409,10 @@ void IghStatus(Igh * drv)
ParPrintf(drv, eError, "IGH switched to local");
*code = EASE_FAULT;
drv->remote = 1;
return;
return 1;
}
*/
return 1;
}
/*----------------------------------------------------------------------------*/
@ -401,10 +435,11 @@ static long IghRead(long pc, void *object)
switch (pc) {
default: /* FSM BEGIN ****************************** */
EasePchk(drv);
redo1:
EaseWrite(eab, "X");
return __LINE__;
case __LINE__: /**********************************/
IghStatus(drv);
if (!IghStatus(drv)) goto redo1;
if (!drv->remote)
goto skiprmt;
EaseWrite(eab, "C0");
@ -532,8 +567,14 @@ static long IghRead(long pc, void *object)
delta = (now - drv->v6time) / 2.64; /* speed: 1/2.64 %/sec */
drv->v6time = now;
if (drv->v6pos > drv->mv[V6] + delta) {
if (drv->v6pos > 99.9) {
drv->v6pos = 99.9;
}
drv->v6pos -= delta;
} else if (drv->v6pos < drv->mv[V6] - delta) {
if (drv->v6pos < 0) {
drv->v6pos = 0;
}
drv->v6pos += delta;
} else {
drv->v6pos = drv->mv[V6];
@ -609,6 +650,8 @@ static long IghRead(long pc, void *object)
if (EaseCheckDoit(eab) || drv->extVersion == 0)
goto quit;
drv->pumpoffcnt = 0;
redo2:
EaseWrite(eab, "{r}");
return __LINE__;
case __LINE__: /**********************************/
@ -625,11 +668,18 @@ static long IghRead(long pc, void *object)
drv->lowerN2 = PAR_NAN;
}
if (!switched_off) goto quit;
/* veryfy pump control */
if (drv->extVersion == 2) {
ParPrintf(eab, eLogError,
"ERROR: overpressure after 3He pump (IGNORED!)");
goto quit;
}
/* verify pump control */
EaseWrite(eab, "X");
return __LINE__;
case __LINE__: /**********************************/
IghStatus(drv);
if (!IghStatus(drv)) goto redo2;
drv->pumpoffcnt++;
if (drv->pumpoffcnt < 3) goto redo2;
if (drv->v[HE3] == 0) goto quit; /* switched off intentionally */
/* overpressure switch activated: we switch pump control off */
EaseWrite(eab, "C3");
@ -740,10 +790,11 @@ static long IghSet(long pc, void *object)
OxiSet(eab, "K", drv->sorbS, 1);
return __LINE__;
case __LINE__: /**********************************/
redo1:
EaseWrite(eab, "X");
return __LINE__;
case __LINE__: /**********************************/
IghStatus(drv);
if (!IghStatus(drv)) goto redo1;
if (drv->o == 2 || drv->o == 3)
goto loop;
if (drv->o % 2) {
@ -756,10 +807,11 @@ static long IghSet(long pc, void *object)
goto loop;
set_sorb_pow:
redo2:
EaseWrite(eab, "X");
return __LINE__;
case __LINE__: /**********************************/
IghStatus(drv);
if (!IghStatus(drv)) goto redo2;
if (drv->o <= 1)
goto skipSetO;
if (drv->o % 2) {
@ -790,10 +842,11 @@ static long IghSet(long pc, void *object)
OxiSet(eab, "S", drv->stillP, 1);
return __LINE__;
case __LINE__: /**********************************/
redo3:
EaseWrite(eab, "X");
return __LINE__;
case __LINE__: /**********************************/
IghStatus(drv);
if (!IghStatus(drv)) goto redo3;
snprintf(buf, sizeof buf, "O%d", drv->o | 1);
EaseWrite(eab, buf);
return __LINE__;
@ -941,6 +994,8 @@ static int IghInit(SConnection * con, int argc, char *argv[], int dynamic)
if (drv == NULL)
return 0;
drv->opentime = 0;
drv->badcnt = 0;
drv->pumpoffcnt = 0;
return 1;
}

View File

@ -287,6 +287,7 @@ void IpsParDef(void *object)
ParCmd(IpsConfirm, NULL);
EaseBasePar(drv);
EaseRunPar(drv);
EaseSendPar(drv);
ParStdDef();
@ -369,7 +370,7 @@ static void IpsStatus(Ips * drv)
drv->remote = 3; /* signal to switch back to C0 local locked */
}
if (drv->d.hwstate == HWBusy && drv->d.b.doit == NULL) {
drv->d.hwstate = HWIdle;
EaseUpdateHwstate(drv, HWIdle);
drv->d.stopped = 0;
}
}
@ -604,7 +605,7 @@ static long IpsStart(long pc, void *object)
Tcl_Interp *pTcl = NULL;
int iRet;
char msg[256];
char *script;
switch (pc) {
default: /* FSM BEGIN ****************************** */
@ -682,7 +683,10 @@ static long IpsStart(long pc, void *object)
if (drv->startScript && drv->startScript[0] != '\0'
&& 0 != strcmp(drv->startScript, "0")) {
pTcl = InterpGetTcl(pServ->pSics);
iRet = Tcl_Eval(pTcl, drv->startScript);
script = strdup(drv->startScript);
iRet = Tcl_Eval(pTcl, script);
free(script);
if (iRet != TCL_OK) {
snprintf(msg, sizeof msg, "%s", pTcl->result);
EaseStop(eab, msg);
@ -725,7 +729,7 @@ static long IpsChangeField(long pc, void *object)
}
EaseSetUpdate(eab, EASE_RUN, 0);
if (drv->nowait) {
drv->d.hwstate = HWIdle;
EaseUpdateHwstate(drv, HWIdle);
drv->d.eMode = EVMonitor; /* finish drive, continue in background */
}
EaseWrite(eab, "F7"); /* switch to tesla on display */
@ -924,7 +928,7 @@ static long IpsChangeField(long pc, void *object)
if (drv->trainMode == 0) {
drv->trainMode = 3; /* remember that we must go to train mode */
}
drv->trainedTo = fabs(fld);
drv->trainedTo = fabs(drv->current);
} else {
if (drv->trainMode == 1) {
drv->trainMode = 2; /* remember that we must go to fast mode */
@ -946,7 +950,7 @@ static long IpsChangeField(long pc, void *object)
goto ramping;
target_reached:
drv->d.hwstate = HWIdle;
EaseUpdateHwstate(drv, HWIdle);
drv->d.eMode = EVMonitor; /* we are at field, drive has finished */
if (drv->persmode != 1)
goto hold_finish;
@ -987,7 +991,7 @@ static long IpsChangeField(long pc, void *object)
finish:
EaseWrite(eab, "C0");
drv->remote = 0; /* local state */
drv->d.hwstate = HWIdle;
EaseUpdateHwstate(drv, HWIdle);
drv->tim = time(NULL); /* time of last field change */
return __LINE__;
case __LINE__: /**********************************/

View File

@ -9,6 +9,12 @@
.tc.c:
tjxp $*.tc $*.c
MZOBJ=fsm.o sugar.o pardef.o ease.o strobj.o oxinst.o \
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
linadriv.o haakedriv.o seaclientprot.o dumprot.o
COREOBJ=phytron.o pfeifferprot.o
OBJ=psi.o buffer.o ruli.o sps.o pimotor.o \
pipiezo.o sanswave.o faverage.o spss7.o\
amorstat.o tasinit.o ptasdrive.o tasutil.o tasscan.o swmotor.o \
@ -23,24 +29,27 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o \
dgrambroadcast.o sinq.o tabledrive.o sinqhttpopt.o\
ritastorage.o el737hpdrivsps.o \
rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \
pfeifferprot.o termprot.o phytron.o autowin.o eigera2.o \
jvlprot.o \
termprot.o autowin.o eigera2.o jvlprot.o \
eigermono.o sputterprot.o zwickroll.o astriumnet.o poldifold.o \
zebraswap.o
zebraswap.o \
$(COREOBJ)
SEAOBJ=sea_psi.o $(MZOBJ) $(COREOBJ)
#epicsadapter.o
.SECONDARY.: sanslirebin.c
MZOBJ=fsm.o sugar.o pardef.o ease.o strobj.o oxinst.o \
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
linadriv.o haakedriv.o seaclientprot.o dumprot.o
libpsi.a: $(OBJ)
rm -f libpsi.a
ar cr libpsi.a $(OBJ)
ranlib libpsi.a
libseapsi.a: $(SEAOBJ)
rm -f libseapsi.a
ar cr libseapsi.a $(SEAOBJ)
ranlib libseapsi.a
clean:
rm -f *.a *.o *.d

312
pardef.c
View File

@ -15,9 +15,12 @@ Markus Zolliker, March 2005
#include <limits.h>
#include <ctype.h>
#include "logger.h"
#include "logsetup.h"
#include "pardef.h"
#include "sugar.h"
#include "dynstring.h"
#include "sicshipadaba.h"
#include "ease.h"
#define ILLNUM -2
#define ILLARGC -3
@ -28,7 +31,10 @@ Markus Zolliker, March 2005
#define PARUNDEF -8
#define ERRCMD -9
typedef enum { NO_OP, FMT_OP, SET_OP, GET_OP, INIT_OP } ParOp;
Logger dummy_logger;
Logger *secop_logger = &dummy_logger; /* disable parlog, and do it with hdb logger */
typedef enum { NO_OP, FMT_OP, SET_OP, GET_OP, INIT_OP, UPD_OP } ParOp;
/* Context holds all the information needed during the pardef function */
typedef struct Context {
@ -58,6 +64,7 @@ typedef struct Context {
int exact;
char *callName; /* the called name of the object (different from obj->name in case of an alias) */
int enumText; /* show enum text */
hdbValue *hvalue;
} Context;
static char *loggerDir = NULL;
@ -293,6 +300,7 @@ static int ParSaveAll(void *object, char *name, FILE * fil)
ParDo(0, o, PAR_SAVE, NULL);
if (o->creationCmd) {
fprintf(fil, "%s endinit\n\n", name);
/* fprintf(fil, "put_secop_info %s\n\n", name); */
}
ctx->saveFile = NULL;
ret = ctx->returnValue;
@ -308,7 +316,15 @@ FILE *ParSaveFile(void)
}
return NULL;
}
/*--------------------------------------------------------------------------*/
void ParUpdateAll(void *object)
{
ParData *o = ParCheck(&parClass, object);
ParBegin();
ParDo(0, o, PAR_UPDATE, NULL);
ParEnd();
}
/*--------------------------------------------------------------------------*/
int ParLog(void *object)
{
@ -327,14 +343,16 @@ int ParLog(void *object)
ctx->now = time(NULL);
next = ctx->now - (o->logTime / o->period + 1) * o->period;
if (next < 0) {
ParEnd();
return 1;
}
showTime = 1;
ParDo(0, o, PAR_LOG, NULL);
o->logTime = ctx->now;
o->logPending = 0;
ParEnd();
if (!secop_logger) {
ParDo(0, o, PAR_LOG, NULL);
o->logTime = ctx->now;
o->logPending = 0;
ParEnd();
}
ParUpdateAll(o);
return 0;
}
@ -347,12 +365,15 @@ void ParLogForced(void *object)
ParBegin();
ctx->now = time(NULL);
showTime = 1;
ParDo(0, o, PAR_LOG, NULL);
o->logTime = ctx->now;
if (o->logPending) {
o->logPending = 2; /* tell ParLog that we are done already, but task is still pending */
if (!secop_logger) {
ParDo(0, o, PAR_LOG, NULL);
o->logTime = ctx->now;
if (o->logPending) {
o->logPending = 2; /* tell ParLog that we are done already, but task is still pending */
}
ParEnd();
}
ParEnd();
ParUpdateAll(o);
}
/*-------------------------------------------------------------------------*/
@ -474,7 +495,7 @@ static int ParExecute(SConnection * con, SicsInterp * sics, void *object,
ParData *o = ParCheck(&parClass, object);
char *setArgv[2];
ParInfo *info;
/* debugging
int i;
printf("ParExecute");
@ -519,29 +540,27 @@ static int ParExecute(SConnection * con, SicsInterp * sics, void *object,
SCSendOK(con);
ctx->returnValue = 1;
}
} else
if ((0 == strcasecmp(argv[1], "log")
} else if ((0 == strcasecmp(argv[1], "log")
|| 0 == strcasecmp(argv[1], "unlog"))) {
if (argc < 3) {
ctx->returnValue = ILLARGC;
ctx->thisPar = argv[1];
} else {
} else if (!secop_logger) {
ctx->argc = argc - 3;
ctx->argv = argv + 3;
ctx->doit = toupper(argv[1][0]) != 'U';
ctx->exact = 0;
ParDo(con, o, PAR_LOGSWITCH, argv[2]);
}
} else
if ((0 == strcasecmp(argv[1], "save")
} else if ((0 == strcasecmp(argv[1], "save")
|| 0 == strcasecmp(argv[1], "unsave"))) {
if (argc != 3) {
ctx->returnValue = ILLARGC;
} else {
} else if (!secop_logger) {
ctx->doit = toupper(argv[1][0]) != 'U';
ParDo(con, o, PAR_SAVESWITCH, argv[2]);
SCparChange(con);
}
SCparChange(con);
} else if (strcmp(argv[1], "interest") == 0) {
if (!o->pCall) {
o->pCall = CreateCallBackInterface();
@ -620,7 +639,7 @@ static int ParExecute(SConnection * con, SicsInterp * sics, void *object,
/*----------------------------------------------------------------------------*/
static void KillLogger(ParInfo * par)
{
if (par->log != NULL) {
if (par->log != NULL && par->log != secop_logger) {
LoggerKill(par->log);
if (par->sugarStatus == 1) {
RemoveCommand(pServ->pSics, LoggerName(par->log));
@ -651,9 +670,11 @@ int ParSwitchLog(int on, char *name)
loggerDir = "./";
LoggerSetDir(loggerDir);
}
ctx->par->log = LoggerMake(name, ctx->obj->period, ctx->exact);
if (ctx->par->log == NULL) {
return BADLOG;
if (!secop_logger) {
ctx->par->log = LoggerMake(name, ctx->obj->period, ctx->exact);
if (ctx->par->log == NULL) {
return BADLOG;
}
}
if (ctx->par->sugarStatus == 0 && name != buf
&& strcmp(name, buf) != 0) {
@ -704,6 +725,7 @@ void ParFind(void)
p->saveIt = 0;
p->saveLog = 0;
p->state = PAR_ALWAYS_READY;
p->node = NULL;
p->next = *last;
*last = p;
}
@ -773,6 +795,7 @@ void ParName(char *name)
switch (ctx->act) {
case PAR_SHOW:
case PAR_SET:
case PAR_HDBSET:
ctx->enumList = NULL;
if (0 == strcasecmp(name, ctx->thisPar)) {
ctx->access = -1;
@ -813,6 +836,9 @@ void ParName(char *name)
ctx->action = PAR_NOOP;
}
return;
case PAR_UPDATE:
ctx->doit = 0; /* affects visibility */
break;
case PAR_SAVE:
case PAR_KILL:
case PAR_NOOP:
@ -922,8 +948,12 @@ ParOp ParWhat(int numeric)
} else {
lname = NULL;
}
ParSwitchLog(1, lname);
LoggerSetNumeric(ctx->par->log, numeric);
if (secop_logger) {
ctx->par->log = secop_logger;
} else {
ParSwitchLog(1, lname);
LoggerSetNumeric(ctx->par->log, numeric);
}
}
}
return INIT_OP;
@ -934,6 +964,7 @@ ParOp ParWhat(int numeric)
}
ctx->returnValue = 1;
return FMT_OP;
case PAR_HDBSET:
case PAR_SET:
if (ctx->returnValue) {
ctx->returnValue = AMBIGUOS;
@ -971,6 +1002,8 @@ ParOp ParWhat(int numeric)
break;
}
return GET_OP;
case PAR_UPDATE:
return UPD_OP;
default:
return NO_OP;
}
@ -1078,6 +1111,7 @@ void ParOut(char *buf)
ParPrintf(NULL, eValue, "%s%s%s = %s", ctx->callName,
p, ctx->parName, buf);
break;
case PAR_HDBSET:
case PAR_SET:
if (ctx->parName[0]) {
p = " ";
@ -1178,6 +1212,8 @@ void ParList(char *group)
} else if (ctx->doit < 0) {
ctx->doit = 0;
}
} else if (ctx->action == PAR_UPDATE) {
ctx->doit = group == NULL || group[0] != '\0';
}
}
@ -1186,6 +1222,8 @@ void ParTail(char *tail)
{
if (ctx->action == PAR_LIST) {
ctx->listTail = tail;
} else if (ctx->action == PAR_UPDATE) {
ctx->doit = 1; /* always visible */
}
}
@ -1215,6 +1253,117 @@ void ParHasChanged(void)
}
}
}
/*----------------------------------------------------------------------------*/
static hdbCallbackReturn ParUpdateCB(pHdb node, void *userData, pHdbMessage msg) {
hdbDataMessage *setMsg;
if ((setMsg = GetHdbSetMessage(msg))){
ParBegin();
ctx->hvalue = setMsg->v;
ParDo(NULL, userData, PAR_HDBSET, node->name);
ParEnd();
}
return hdbContinue;
}
/*----------------------------------------------------------------------------*/
void ParUpdateNode(hdbValue value) {
pHdb node;
char sicscommand[128];
char path[128];
char secop_id[128];
int skip_unchanged = 1;
if (!ctx->obj->node) {
ctx->obj->secop_module = ctx->obj->name;
if (ctx->parName[0]) {
/* main node is not yet created -> assume it is of type NONE */
node = MakeHipadabaNode(ctx->obj->name, HIPNONE, 0);
if (ctx->obj->secop_module) {
SetHdbProperty(node, "secop_module", ctx->obj->secop_module);
}
} else {
node = MakeSICSHdbPar(ctx->obj->name, ctx->access, value);
if (ctx->par->log && ctx->obj->secop_module) {
snprintf(secop_id, sizeof secop_id, "%s:value", ctx->obj->secop_module);
SetHdbProperty(node, "secop_id", secop_id);
snprintf(path, sizeof path, "/%s", ctx->obj->name);
LogMakeInternal(node, path, 0); /* secop_module */
skip_unchanged = 0;
}
}
ctx->obj->node = node;
AddHipadabaChild(GetHipadabaRoot(), node, NULL);
SetHdbProperty(node, "sicscommand", ctx->obj->name);
SetHdbProperty(node, "group", "_pardef_");
}
node = ctx->par->node;
if (node == NULL) { /* node is not yet set */
if (ctx->parName[0]) {
if (strchr(ctx->parName, '/') != NULL) {
return; /* do not allow parameter names containing '/' */
}
node = AddSICSHdbPar(ctx->obj->node, ctx->parName, ctx->access, value);
if (ctx->par->log && ctx->obj->secop_module) {
snprintf(secop_id, sizeof secop_id, "%s:%s", ctx->obj->secop_module, ctx->parName);
SetHdbProperty(node, "secop_id", secop_id);
snprintf(path, sizeof path, "/%s/%s", ctx->obj->name, ctx->parName);
LogMakeInternal(node, path, 0);
skip_unchanged = 0;
}
ctx->par->node = node;
snprintf(sicscommand, sizeof sicscommand, "%s %s", ctx->obj->name, ctx->parName);
} else {
/* bare object (parameter "") */
node = ctx->obj->node;
snprintf(sicscommand, sizeof sicscommand, "%s = ", ctx->obj->name);
}
SetHdbProperty(node, "sicscommand", sicscommand);
AppendHipadabaCallback(node, MakeHipadabaCallback(ParUpdateCB, ctx->obj, NULL));
}
if (ctx->action == PAR_UPDATE) {
char *visible = GetHdbProp(node, "visible");
if (ctx->doit) {
if (visible) {
SetHdbProperty(node, "visible", NULL);
}
} else {
if (!visible || strcasecmp(visible, "false") != 0) {
SetHdbProperty(node, "visible", "false");
}
}
switch (value.dataType) {
case HIPFLOAT:
if (value.v.doubleValue == PAR_NAN) {
if (GetHdbProp(node, "geterror") == NULL) {
SetHdbProperty(node, "geterror", "undefined");
value.v.doubleValue = 0;
UpdateHipadabaPar(node, value, ctx->con);
}
return;
}
if (skip_unchanged && node->value.v.doubleValue == value.v.doubleValue) return;
break;
case HIPINT:
if (value.v.intValue == PAR_LNAN) {
if (GetHdbProp(node, "geterror") == NULL) {
SetHdbProperty(node, "geterror", "undefined");
value.v.intValue = 0;
UpdateHipadabaPar(node, value, ctx->con);
}
return;
}
if (skip_unchanged && node->value.v.intValue == value.v.intValue) return;
break;
case HIPTEXT:
if (strcmp(node->value.v.text, value.v.text) == 0) return;
break;
default:
return;
}
}
SetHdbProperty(node, "geterror", NULL);
UpdateHipadabaPar(node, value, ctx->con);
}
/*----------------------------------------------------------------------------*/
void ParFloat(float *value, float defValue)
@ -1225,6 +1374,10 @@ void ParFloat(float *value, float defValue)
switch (ParWhat(1)) {
case SET_OP:
if (ctx->action == PAR_HDBSET) {
*value = ctx->hvalue->v.doubleValue;
break;
}
if (ctx->argc > 1) {
ctx->returnValue = ILLARGC;
return;
@ -1262,6 +1415,10 @@ void ParFloat(float *value, float defValue)
break;
case INIT_OP:
*value = defValue;
ParUpdateNode(MakeHdbFloat(*value));
break;
case UPD_OP:
ParUpdateNode(MakeHdbFloat(*value));
break;
case NO_OP:
break;
@ -1277,6 +1434,10 @@ void ParInt(int *value, int defValue)
switch (ParWhat(1)) {
case SET_OP:
if (ctx->action == PAR_HDBSET) {
*value = ctx->hvalue->v.intValue;
break;
}
if (ctx->argc > 1) {
ctx->returnValue = ILLARGC;
return;
@ -1309,6 +1470,10 @@ void ParInt(int *value, int defValue)
break;
case INIT_OP:
*value = defValue;
ParUpdateNode(MakeHdbInt(defValue));
break;
case UPD_OP:
ParUpdateNode(MakeHdbInt(*value));
break;
default:
break;
@ -1319,11 +1484,17 @@ void ParInt(int *value, int defValue)
void ParStr(char **value, char *defValue)
{
static char *empty = "";
char *to_free;
switch (ParWhat(0)) {
case SET_OP:
if (*value != NULL)
free(*value);
to_free = *value;
if (ctx->action == PAR_HDBSET) {
if (to_free) free(to_free);
*value = strdup(ctx->hvalue->v.text);
break;
}
if (to_free) free(to_free);
if (ctx->argc > 0 && strcmp(ctx->argv[0], "=") == 0) {
*value = ParArg2Str(ctx->argc - 1, ctx->argv + 1, NULL, 0);
} else {
@ -1332,14 +1503,26 @@ void ParStr(char **value, char *defValue)
ParHasChanged();
/* fall through */
case FMT_OP:
if (*value == NULL)
value = &empty;
ParOut(*value);
if (*value == NULL) {
ParOut(empty);
} else {
ParOut(*value);
}
break;
case INIT_OP:
ctx->exact = 1;
if (defValue != NULL) {
if (defValue == NULL) {
ParUpdateNode(MakeHdbText(""));
} else{
*value = strdup(defValue);
ParUpdateNode(MakeHdbText(*value));
}
break;
case UPD_OP:
if (*value == NULL) {
ParUpdateNode(MakeHdbText(""));
} else {
ParUpdateNode(MakeHdbText(*value));
}
break;
default:
@ -1357,6 +1540,10 @@ void ParFixedStr(char *value, int maxsize, char *defValue)
switch (ParWhat(0)) {
case SET_OP:
if (ctx->action == PAR_HDBSET) {
snprintf(value, maxsize, "%s", ctx->hvalue->v.text);
break;
}
ParArg2Str(ctx->argc, ctx->argv, value, maxsize);
ParHasChanged();
/* fall through */
@ -1367,10 +1554,16 @@ void ParFixedStr(char *value, int maxsize, char *defValue)
break;
case INIT_OP:
ctx->exact = 1;
if (defValue != NULL) {
if (defValue == NULL) {
ParUpdateNode(MakeHdbText(""));
} else{
snprintf(value, maxsize, "%s", defValue);
ParUpdateNode(MakeHdbText(value));
}
break;
case UPD_OP:
ParUpdateNode(MakeHdbText(value));
break;
default:
break;
}
@ -1464,6 +1657,36 @@ void ParGetFloat(SConnection * con, void *object, char *name, float *value)
ParEnd();
}
/*----------------------------------------------------------------------------*/
void ParKillThisPar(ParInfo *p)
{
p->next = NULL;
if (p->node) {
RemoveSICSPar(p->node, NULL);
}
KillLogger(p);
if (p->name) {
free(p->name);
}
free(p);
}
/*----------------------------------------------------------------------------*/
void ParKillPar(void *object, char *name)
{
ParData *o = object;
ParInfo *p, **last;
last = &o->infoList;
for (p=o->infoList; p!=NULL; last=&p->next, p=p->next) {
if (strcasecmp(name, p->name) == 0) {
*last = p->next;
ParKillThisPar(p);
return;
}
}
}
/*----------------------------------------------------------------------------*/
void ParKill(void *object)
{
@ -1485,14 +1708,13 @@ void ParKill(void *object)
p = o->infoList;
while (p) {
q = p->next;
p->next = NULL;
KillLogger(p);
if (p->name) {
free(p->name);
}
free(p);
ParKillThisPar(p);
p = q;
}
if (o->node) {
RemoveSICSPar(o->node, NULL); /* this deletes also all children */
o->node = NULL;
}
if (o->logPending) { /* will be free in scheduled ParLog function */
o->desc = NULL;
} else {
@ -1510,15 +1732,22 @@ void ParKill(void *object)
}
/*----------------------------------------------------------------------------*/
void ParInitPar(void *object, char *name)
void ParInitPar(void *object, char *name, int logged)
{
ParBegin();
ctx->obj = object;
ctx->parName = name;
ctx->par = NULL;
ParFind();
ParSwitchLog(1, NULL);
if (logged) {
if (secop_logger) {
if (ctx->par) {
ctx->par->log = secop_logger;
}
} else {
ParSwitchLog(1, NULL);
}
}
ParEnd();
}
@ -1558,6 +1787,7 @@ void *ParMake(SConnection * con, char *name, ParClass * class,
o->verbose = 0;
o->logPending = 0;
o->conn = NULL;
o->node = NULL;
ParSaveConn(o, con);
o->pardef = pardef;
ParBegin();

View File

@ -12,6 +12,7 @@ Markus Zolliker, March 2005
#include "sics.h"
#include "logger.h"
#include "hipadaba.h"
int ParPrintf(void *object, int iOut, const char *fmt, ...);
@ -25,6 +26,7 @@ typedef struct ParInfo {
int saveLog; /* bool */
ReadyState state; /* enum ReadyState */
int sugarStatus; /* =1: sugar object made */
pHdb node; /* node for update */
} ParInfo;
#define PAR_LEVELS 8
@ -53,6 +55,8 @@ typedef struct ParData {
pICallBack pCall; /* sics callback function */
SConnection *conn; /* last connection with user or manager priv. */
int verbose; /* verbosity, mainly for tests */
pHdb node; /* node for update */
char *secop_module; /* secop module name, if enabled */
} ParData;
/*
@ -174,7 +178,9 @@ typedef enum {
PAR_LOGSWITCH, /* (de)activate single parameter for logging (1) */
PAR_SAVE, /* save all parameters activated for saving (2) */
PAR_SAVESWITCH, /* (de)activate single parameter for saving (1) */
PAR_KILL /* kill content (called before remove) */
PAR_KILL, /* kill content (called before remove) */
PAR_UPDATE, /* update hipadaba node */
PAR_HDBSET /* set from hipadaba node */
} ParAct;
int ParActionIs(ParAct action);
@ -203,6 +209,7 @@ char *ParGetValueArg(); /* get the set argument for floats and ints. If
/*
functions to be used outside pardef:
*/
void ParUpdateAll(void *object); /* update all hdb nodes */
int ParLog(void *object); /* log all parameters of this object, but only if not
already logged in the interval, returns >= 0 when done,
or < 0, when not done (execute PAR_LOG action) */
@ -241,7 +248,10 @@ char *ParArg2Str(int argc, char *argv[], char *res, int maxsize);
void ParSaveConn(void *object, SConnection * con);
/* save connection for further use */
void ParInitPar(void *object, char *name);
void ParInitPar(void *object, char *name, int logged);
/* inititalize dynamic parameter */
void ParKillPar(void *object, char *name);
/* delete dynamic parameter */
#endif

182
sea_psi.c Normal file
View File

@ -0,0 +1,182 @@
/*------------------------------------------------------------------------
P S I
This is the site specific interface to SICS for PSI. This file implements
the interface defined in ../site.h
copyright: see file COPYRIGHT
Mark Koennecke, June 2003 - May 2007
Modules initialized with an installation sics command are added to
AddPsiCommands with SCMD.
Modules initialized with a startup C command are added to SiteInit with
INIT.
There is no need to add include statements or prototype declarations for
above items.
However, for drivers added, we still need to declare the prototypes or
include the header file.
Markus Zolliker, Jan 2010
-----------------------------------------------------------------------*/
#include <tcl.h>
#include "sics.h"
#include "site.h"
#include <motor.h>
#include <site.h>
#include "sinqhmdriv.i"
#include "tdchm.h"
#include "itc4.h"
#include "bruker.h"
#include "ltc11.h"
#include "eurodriv.h"
#include "el755driv.h"
#include <evdriver.i>
#include "serial.h"
#include "sinqhttp.h"
/*--------------------------------------------------------------------------*/
void SiteInit(void)
{
#define INIT(F) { void F(void); F(); }
/* insert here initialization routines ... */
INIT(IlmStartup);
INIT(IpsStartup);
INIT(ItcStartup);
INIT(IghStartup);
INIT(Euro2kStartup);
INIT(StrObjStartup);
INIT(ArrayObjStartup);
INIT(LinaStartup);
INIT(HaakeStartup);
/* INIT(MongoLogInit); */
/*
* SICS specific Asynchronous I/O protocols
*/
INIT(AddSeaClientProtocol);
INIT(AddDumProtocol);
INIT(AddPhytronProtocoll);
INIT(AddPfeifferProtocoll);
}
static pSite sitePSI = NULL;
/*
* from tclClock.c
*/
int Tcl_ClockObjCmd (ClientData client, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*----------------------------------------------------------------------*/
static void AddPsiCommands(SicsInterp * pInter)
{
/* declare and add permanent command */
#define PCMD(NAME, FUN) { \
int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \
int argc, char *argv[]); \
AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 0); \
}
/* declare and add startup command */
#define SCMD(NAME, FUN) { \
int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \
int argc, char *argv[]); \
AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 1); \
}
/* alphabetic order */
/* SCMD("SerialInit", SerialInit); */
PCMD("cnvrt", CnvrtAction);
/*
* Tcl 8.5 has implemented the clock command in tcl rather then C.
* This includes the same command, backported from Tcl 8.4
*/
Tcl_CreateObjCommand(InterpGetTcl(pServ->pSics), "clock", Tcl_ClockObjCmd, NULL, NULL);
/*
SCMD("MakeDifrac",MakeDifrac);
*/
}
/*-------------------------------------------------------------------*/
static pMotor CreatePsiMotor(SConnection * pCon, int argc, char *argv[])
{
pMotor pNew = NULL;
return pNew;
}
/*-------------------------------------------------------------------*/
static pCounterDriver CreatePsiCounterDriver(SConnection * pCon,
int argc, char *argv[])
{
pCounterDriver pNew = NULL;
return pNew;
}
/*-------------------------------------------------------------------*/
static pCodri CreatePsiController(SConnection * pCon, int argc,
char *argv[])
{
pCodri pNew = NULL;
return pNew;
}
/*------------------------------------------------------------------*/
static pEVControl InstallPsiEnvironmentController(SicsInterp * pSics,
SConnection * pCon,
int argc, char *argv[])
{
return NULL;
}
/*-----------------------------------------------------------------*/
static int ConfigurePsiScan(pScanData self, char *option)
{
return 0;
}
/*--------------------------------------------------------------------*/
static HistDriver *CreatePsiHistMem(char *name, pStringDict pOptions)
{
return NULL;
}
/*--------------------------------------------------------------------*/
static void KillPsi(void *site)
{
free(site);
sitePSI = NULL;
}
/*---------------------------------------------------------------------
The scheme here goes along the lines of the singleton design pattern
---------------------------------------------------------------------*/
pSite getSite(void)
{
if (sitePSI == NULL) {
sitePSI = (pSite) malloc(sizeof(Site));
/*
we cannot go on if we do not even have enough memory to allocate
the site data structure
*/
assert(sitePSI);
/*
initializing function pointers
*/
sitePSI->AddSiteCommands = AddPsiCommands;
sitePSI->RemoveSiteCommands = NULL;
sitePSI->CreateMotor = CreatePsiMotor;
sitePSI->CreateCounterDriver = CreatePsiCounterDriver;
sitePSI->CreateHistogramMemoryDriver = CreatePsiHistMem;
sitePSI->CreateVelocitySelector = NULL;
sitePSI->CreateControllerDriver = CreatePsiController;
sitePSI->InstallEnvironmentController =
InstallPsiEnvironmentController;
sitePSI->ConfigureScan = ConfigurePsiScan;
sitePSI->KillSite = KillPsi;
}
return sitePSI;
}