diff --git a/arrobj.c b/arrobj.c index cf78f0c..467c4dd 100644 --- a/arrobj.c +++ b/arrobj.c @@ -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; diff --git a/ease.c b/ease.c index 6b6f186..acbc87d 100644 --- a/ease.c +++ b/ease.c @@ -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); } diff --git a/ease.h b/ease.h index 640a6ac..2530441 100644 --- a/ease.h +++ b/ease.h @@ -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, diff --git a/euro2kdriv.c b/euro2kdriv.c index c568137..8298a34 100644 --- a/euro2kdriv.c +++ b/euro2kdriv.c @@ -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; diff --git a/ighdriv.c b/ighdriv.c index 81bbb16..5f6c74a 100644 --- a/ighdriv.c +++ b/ighdriv.c @@ -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; } diff --git a/ipsdriv.c b/ipsdriv.c index 2a7343c..5e1dd42 100644 --- a/ipsdriv.c +++ b/ipsdriv.c @@ -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__: /**********************************/ diff --git a/make_gen b/make_gen index 1cf8562..af9a80b 100644 --- a/make_gen +++ b/make_gen @@ -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 diff --git a/pardef.c b/pardef.c index 60d3b51..dee8048 100644 --- a/pardef.c +++ b/pardef.c @@ -15,9 +15,12 @@ Markus Zolliker, March 2005 #include #include #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 = ∅ - 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(); diff --git a/pardef.h b/pardef.h index 819af17..562a5b4 100644 --- a/pardef.h +++ b/pardef.h @@ -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 diff --git a/sea_psi.c b/sea_psi.c new file mode 100644 index 0000000..47a6ec5 --- /dev/null +++ b/sea_psi.c @@ -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 +#include "sics.h" +#include "site.h" +#include +#include +#include "sinqhmdriv.i" +#include "tdchm.h" +#include "itc4.h" +#include "bruker.h" +#include "ltc11.h" +#include "eurodriv.h" +#include "el755driv.h" +#include +#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; +}