diff --git a/dilludriv.c b/dilludriv.c index 5937834..cda811b 100644 --- a/dilludriv.c +++ b/dilludriv.c @@ -20,9 +20,7 @@ #include #include - typedef struct __EVDriver *pEVDriver; - -#include +#include "evdriver.h" #include "hardsup/dillutil.h" #include "hardsup/el734_def.h" #include "hardsup/el734fix.h" diff --git a/el755driv.c b/el755driv.c index cceafb1..686d635 100644 --- a/el755driv.c +++ b/el755driv.c @@ -18,9 +18,7 @@ #include #include - typedef struct __EVDriver *pEVDriver; - -#include +#include "evdriver.h" #include "hardsup/el755_def.h" #include "hardsup/el755_errcodes.h" #include "hardsup/sinq_prototypes.h" diff --git a/eurodriv.c b/eurodriv.c index 191ebca..1bbbfdd 100644 --- a/eurodriv.c +++ b/eurodriv.c @@ -22,9 +22,7 @@ #include #include - typedef struct __EVDriver *pEVDriver; - -#include +#include "evdriver.h" #include "hardsup/el734_def.h" #include "hardsup/el734fix.h" #include "hardsup/serialsinq.h" diff --git a/eve.c b/eve.c index b310be3..eef58ed 100644 --- a/eve.c +++ b/eve.c @@ -26,9 +26,9 @@ Markus Zolliker, Sept 2004 #define ILLNUM -1456 #define ILLARGC -1457 #define AMBIGUOS -1458 -#define UNCHANGEABLE -1459 #define ILLPRIV -1460 #define BADLOG -1461 +#define BUSY -1462 typedef enum { cntAction, iniAction, parAction, listAction, @@ -140,9 +140,7 @@ char *EveInt2Text(char *list[], int num) { /*----------------------------------------------------------------------------*/ int EveCheckRights(EveParArg *arg, int access) { - if (access == usInternal) { - arg->ret = UNCHANGEABLE; - } else if (SCMatchRights(arg->pCon,access)) { + if (SCMatchRights(arg->pCon,access)) { return 1; } else { arg->ret = ILLPRIV; @@ -181,10 +179,9 @@ EvePar *EveThisPar(EveParArg *arg, char *name, int flags) { if (!eve->par) return NULL; assert(arg->idx < eve->npar); par = eve->par + arg->idx; - /* arg->idx ++ */ if (par->name == NULL) { par->name = name; - if (flags & 2) { /* first time: default logger */ + if (flags & EVE_LOGPAR) { /* first time: default logger */ EveSwitchLog(eve, par, 1); } } else { @@ -252,12 +249,12 @@ ArgOp EveOp(EveParArg *arg, char *name, char **fmt, int access, int flags) { arg->idx ++; return noOp; case listAction: - if (flags & 1) { + if (flags & EVE_ACTPAR) { return fmtOp; } return noOp; case logAction: - if (flags & 1) { + if (flags & EVE_ACTPAR) { op = fmtOp; break; /* reduce fmt */ } @@ -295,7 +292,7 @@ ArgOp EveOp(EveParArg *arg, char *name, char **fmt, int access, int flags) { } return noOp; case saveAction: - if (flags & 4) { + if (flags & EVE_SAVEPAR) { op = fmtOp; break; /* reduce fmt */ } @@ -320,8 +317,10 @@ ArgOp EveOp(EveParArg *arg, char *name, char **fmt, int access, int flags) { /*----------------------------------------------------------------------------*/ void EveOut(EveParArg *arg, char *name, char *buf) { EvePar *par; - int l, i, j, m, ln, lp; + int l, i, j, m, ln, lp, iret; char *p, *q, *tab; + char buffer[256]; + char *dot; switch (arg->action) { case listAction: @@ -367,7 +366,16 @@ void EveOut(EveParArg *arg, char *name, char *buf) { par = EveThisPar(arg, name, 0); arg->idx ++; if (par->log) { - LoggerWrite(par->log, arg->now, arg->period, buf); + 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: @@ -394,6 +402,7 @@ void EveFloatPar(EveParArg *arg, char *name, float *value, char *fmt, break; } *value = f; + SCparChange(arg->pCon); /* fall through */ case fmtOp: snprintf(buf, sizeof buf, fmt, *value); @@ -419,6 +428,7 @@ void EveIntPar(EveParArg *arg, char *name, int *value, int access, int flags) { break; } *value = i; + SCparChange(arg->pCon); /* fall through */ case fmtOp: snprintf(buf, sizeof buf, "%d", *value); @@ -438,6 +448,7 @@ void EveStrPar(EveParArg *arg, char *name, char **value, int maxsize, int access } else { /* fixed string */ EveArg2Text(arg->argc, arg->argv, *value, maxsize); } + SCparChange(arg->pCon); /* fall through */ case fmtOp: if (*value == NULL) value = ∅ @@ -465,6 +476,7 @@ void EveObPar(EveParArg *arg, int index, char *fmt, int flags) { } else { arg->evc->pParam[index].fVal = f; } + SCparChange(arg->pCon); /* fall through */ case fmtOp: snprintf(buf, sizeof buf, fmt, arg->evc->pParam[index].fVal); @@ -492,6 +504,7 @@ void EveObParEnum(EveParArg *arg, int index, char *list[], int flags) { } else { arg->evc->pParam[index].fVal = i; } + SCparChange(arg->pCon); /* fall through */ case fmtOp: i = (int)ObVal(arg->evc->pParam, index); @@ -517,6 +530,7 @@ void EveEnumPar(EveParArg *arg, char *name, int *value, char *list[], int access arg->ret = ILLNUM; } else { *value = i; + SCparChange(arg->pCon); } /* fall through */ case fmtOp: @@ -540,6 +554,20 @@ void EveCmd(EveParArg *arg, char *name, EveSubCmd subcmd, int access) { } } /*----------------------------------------------------------------------------*/ +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 @@ -580,6 +608,10 @@ 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; @@ -620,9 +652,6 @@ error: case AMBIGUOS: SCPrintf(pCon, eError, "ERROR: doubly defined parameter %s.%s", evc->pName, argv[1]); break; - case UNCHANGEABLE: - SCPrintf(pCon, eError, "ERROR: %s.%s is not changeable", evc->pName, argv[1]); - break; case ILLPRIV: SCPrintf(pCon, eError, "ERROR: Insufficient privilege to change %s.%s", evc->pName, argv[1]); break; @@ -635,6 +664,9 @@ error: 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; } @@ -740,7 +772,7 @@ int EveIdle(long pc, Eve *eve) { rd: if (eve->hwstate == HWBusy) eve->hwstate = HWIdle; FSM_CALL(eve->read); - EveLog(eve); + 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; /* @@ -856,19 +888,17 @@ int EveDontFix(pEVDriver driver, int iError) { return(DEVFAULT); /* severe */ } /*-------------------------------------------------------------------------*/ -int EveSaveStatus(void *data, char *name, FILE *fil) +int EveSavePars(pEVDriver driver, FILE *fil) { - pEVControl evc = data; - Eve *eve = evc->pDriv->pPrivate; + Eve *eve = driver->pPrivate; EveParArg arg; - EVSaveStatus(data, name, fil); arg.action = saveAction; arg.pCon = NULL; - arg.evc = evc; + arg.evc = eve->evc; arg.fil = fil; eve->pardef(eve, &arg); - return 1; + return 2; /* no (duplicate) save of standard parameters ! */ } /*-------------------------------------------------------------------------*/ void EveKill(void *pData) { @@ -880,7 +910,9 @@ void EveKill(void *pData) { assert(eve); KillRS232(eve->ser); for (i=0; inpar; i++) { - LoggerKill(eve->par[i].log); + if (eve->par[i].log) { + LoggerKill(eve->par[i].log); + } eve->par[i].log = NULL; } free(eve); @@ -982,6 +1014,7 @@ pEVControl MakeEveEVC(int argc, char *argv[], Eve *eve, SConnection *pCon) { driver->Send = EveSend; driver->GetError = EveGetError; driver->TryFixIt = EveDontFix; + driver->SavePars = EveSavePars; driver->Init = EveInit; driver->Close = EveClose; diff --git a/eve.h b/eve.h index 82c09fb..0f7ead8 100644 --- a/eve.h +++ b/eve.h @@ -80,6 +80,7 @@ typedef struct Eve { * index: the ObPar index * list: a NULL terminated list of value names * subcmd: a function for handling the subcommand +* fsmFunc: a fsm function to handle a subcommand */ void EveFloatPar(EveParArg *arg, char *name, float *value, char *fmt, int access, int flags); @@ -92,7 +93,9 @@ void EveObParEnum(EveParArg *arg, int index, char *list[], int flags); void EveEnumPar(EveParArg *arg, char *name, int *value, char *list[], int access, int flags); void EveCmd(EveParArg *arg, char *name, EveSubCmd subcmd, int access); - +void EveFloatCmd(EveParArg *arg, char *name, float *value, char *fmt, + FsmFunc fsmFunc, int access, int flags); + /* a collection of parameters from the standard EVController * (limits, tolerance, drive handling, out of tolerance handling) * normally appearing at the top @@ -107,9 +110,15 @@ void EveStdParEnd(EveParArg *arg, char *fmt, int targetFlag); /* return the connection related to the parameter request */ SConnection *EveArgConn(EveParArg *arg); +/* check if it is a user action (parameter list, set or read) */ +int EveUserAction(EveParArg *arg); + /* write to the actual (last driving) connection */ int EvePrintf(Eve *eve, int iOut, char *fmt, ...); +/* evelog has to be called after all read operations */ +void EveLog(Eve *eve); + void EveWriteError(Eve *eve); void EveWrite(Eve *eve, char *cmd); void EveWaitRead(Eve *eve); diff --git a/fsm.c b/fsm.c index d281c5d..4a06480 100644 --- a/fsm.c +++ b/fsm.c @@ -78,6 +78,7 @@ Fsm *FsmStartTask(void *obj, FsmHandler handler, FsmFunc func) { new->func = func; new->handler = handler; new->sp = 0; + new->pause = 0; new->till = 0; return new; } diff --git a/ipsdriv.c b/ipsdriv.c index ffe25a0..03caafb 100644 --- a/ipsdriv.c +++ b/ipsdriv.c @@ -33,6 +33,7 @@ typedef struct { float current; /* current (in Tesla) */ float persfield; /* persistent field from IPS (in Tesla) */ float lastfield; /* persistent field from last drive */ + float confirmfield; /* field confirmed in 1st step */ float ramp; /* actual ramp rate (Telsa/min) */ int persmode; /* 0: leave switch on, 1: go to persistant mode */ int perswitch; /* state of switch */ @@ -43,22 +44,18 @@ typedef struct { time_t tim; } IpsDriv; +int IpsConfirm(SConnection *pCon, pEVControl evc, int argc, char *argv[]); /*----------------------------------------------------------------------------*/ static int IpsOk(IpsDriv *me, SConnection *pCon) { float dif; Eve *eve=&me->eve; - if (!pCon) pCon = SCLoad(&eve->evc->conn); + if (me->eve.version[0]=='\0') return 1; /* connection not yet confirmed */ if (me->perswitch) return 1; - if (fabs(me->persfield - me->lastfield) < 1e-5) { - return 1; - } - if (me->force == 2) { - return 1; - } - if (fabs(me->persfield - me->lastfield) < 1e-5 - || me->force == 2) return 1; + if (fabs(me->persfield - me->lastfield) < 1e-5) return 1; + if (me->force != 0) return 1; eve->errCode = EVE_FAULT; + if (!pCon) pCon = SCLoad(&eve->evc->conn); SCPrintf(pCon, eWarning, "\nit is not sure which field is in the magnet\n" "value stored in power supply: %f\n" @@ -75,12 +72,17 @@ static int IpsOk(IpsDriv *me, SConnection *pCon) { #define S EVE_SAVEPAR void IpsPars(IpsDriv *me, EveParArg *arg) { - IpsOk(me, EveArgConn(arg)); EveIntPar(arg, "persmode", &me->persmode, usUser, A+S); EveIntPar(arg, "perswitch", &me->perswitch, usInternal, A); - EveObPar(arg, UPLIMIT, "%.5g\tT", A+S); - EveFloatPar(arg, "ramp", &me->ramp, "%.5g\tT/min", usUser, A+S); - EveStdParEnd(arg, "%.5g\tT", A+L+S); + EveObPar(arg, UPLIMIT, "%.5g\tTesla", A+S); + EveFloatPar(arg, "ramp", &me->ramp, "%.5g\tTesla/min", usUser, A+S); + EveFloatPar(arg, "current", &me->current, "%.5g\tTesla", usInternal, A+L); + EveFloatPar(arg, "lastfield", &me->lastfield, "%.5g\tTesla", usInternal, S); + EveCmd(arg, "confirm", IpsConfirm, usUser); + EveStdParEnd(arg, "%.5g\tTesla", A+L+S); + if (EveUserAction(arg)) { + IpsOk(me, EveArgConn(arg)); + } } /*----------------------------------------------------------------------------*/ void IpsStatus(IpsDriv *me) { @@ -158,11 +160,12 @@ static int IpsRead(long pc, IpsDriv *me) { EveWrite(eve, "X"); FSM_NEXT IpsStatus(me); /* check for errors and get perswitch */ +/* if (!me->remote) goto rd; EveWrite(eve, "C0"); me->remote = 0; FSM_NEXT - +*/ rd: EveWrite(eve, "R7"); /* read current (in Tesla) */ FSM_NEXT @@ -176,6 +179,7 @@ static int IpsRead(long pc, IpsDriv *me) { IpsSetField(me, OiGetFlt(eve, 3, NULL)); quit: + EveLog(eve); FSM_END } /*----------------------------------------------------------------------------*/ @@ -245,6 +249,7 @@ static int IpsChangeField(long pc, IpsDriv *me) { EveWrite(eve, "R7"); /* read current (in Tesla) */ FSM_NEXT me->current = OiGetFlt(eve, 3, NULL); + EveLog(eve); if (fabs(me->current - me->lastfield) > 1e-5) goto stab1; stab2: @@ -316,6 +321,7 @@ static int IpsChangeField(long pc, IpsDriv *me) { } OiSet(eve, "J", fld, 3); FSM_NEXT + EveLog(eve); goto ramping; target_reached: @@ -388,7 +394,7 @@ int IpsConfirm(SConnection *pCon, pEVControl evc, int argc, char *argv[]) { return -1; } fld=atof(argv[1]); - if (fld < ObVal(evc->pParam, UPLIMIT)) { + if (fld > ObVal(evc->pParam, UPLIMIT)) { SCPrintf(pCon, eError, "Field outside limit"); return -1; } @@ -399,12 +405,12 @@ int IpsConfirm(SConnection *pCon, pEVControl evc, int argc, char *argv[]) { if (fabs(fld - me->persfield) > 1e-5 && fabs(fld - me->lastfield) > 1e-5) { SCPrintf(pCon, eWarning, "Be aware that this does neither match the field" " stored in software\nnor the field stored in power supply."); - me->force = 0; } + if (me->force && fld != me->confirmfield) me->force = 0; if (me->force == 0) { SCPrintf(pCon, eWarning, "Please repeat this command, to confirm again" " the persistent field of\n %f Tesla.", fld); - IpsSetField(me, fld); + me->confirmfield = fld; me->force=1; } else { me->force=2; diff --git a/itc4driv.c b/itc4driv.c index fedf505..ff275ed 100644 --- a/itc4driv.c +++ b/itc4driv.c @@ -47,9 +47,7 @@ #include #include - typedef struct __EVDriver *pEVDriver; - -#include +#include "evdriver.h" #include "hardsup/itc4util.h" #include "hardsup/el734_def.h" #include "hardsup/el734fix.h" diff --git a/itcdriv.c b/itcdriv.c index 5bffa51..c12a18e 100644 --- a/itcdriv.c +++ b/itcdriv.c @@ -34,15 +34,18 @@ typedef struct { float t[4]; /* temperatures (0 unused) */ int dig[4]; /* format for these */ float htr; - float coldvalve; + float gas; int sampleChan; int controlChan; - int gas; + int gasMode; + int htrMode; int remote; int h; /* actual heater channel */ int a; /* actual auto mode */ } ItcDriv; +static long ItcSetGas(long pc, void *obj); +static long ItcSetHtr(long pc, void *obj); /*----------------------------------------------------------------------------*/ #define A EVE_ACTPAR #define L EVE_LOGPAR @@ -53,6 +56,7 @@ void ItcPars(ItcDriv *me, EveParArg *arg) { int i; int flag; char *ti[4] = {"setp","t1","t2","t3"}; + static char *modeList[]={"off", "manual", "auto", NULL }; EveStdPar(arg); @@ -67,13 +71,14 @@ void ItcPars(ItcDriv *me, EveParArg *arg) { } flag = me->controlChan != 0 || me->htr != 0; - EveFloatPar(arg, "htr", &me->htr, "%.1f\t%%", usInternal, flag*A + L); - flag = me->gas > 0; - EveFloatPar(arg, "coldvalve", &me->coldvalve, "%.1f\t%%", usInternal, flag*A + L); + EveEnumPar(arg, "htrMode", &me->htrMode, modeList, usUser, A+S); + EveFloatCmd(arg, "htr", &me->htr, "%.1f\t%%", ItcSetHtr, usUser, flag*A + L); + EveEnumPar(arg, "gasMode", &me->gasMode, modeList, usUser, A+S); + flag = me->gasMode > 0; + EveFloatCmd(arg, "gas", &me->gas, "%.1f\t%%", ItcSetGas, usUser, flag*A + L); EveIntPar(arg, "dig1", &me->dig[1], usUser, S); EveIntPar(arg, "dig2", &me->dig[2], usUser, S); EveIntPar(arg, "dig3", &me->dig[3], usUser, S); - EveIntPar(arg, "gas", &me->gas, usUser, S); EveIntPar(arg, "sampleChan", &me->sampleChan, usUser, A+S); EveIntPar(arg, "controlChan", &me->controlChan, usUser, A+S); sprintf(fmt, "%%.%df\tK", me->dig[me->sampleChan]); @@ -110,7 +115,7 @@ void ItcStatus(ItcDriv *me) { } } /*----------------------------------------------------------------------------*/ -static int ItcRead(long pc, ItcDriv *me) { +static long ItcRead(long pc, ItcDriv *me) { Eve *eve=&me->eve; char *p; int l; @@ -152,21 +157,24 @@ static int ItcRead(long pc, ItcDriv *me) { FSM_NEXT me->t[0] = OiGetFlt(eve, me->dig[me->controlChan], NULL); + if (me->htrMode != 2 && me->a % 2 == 0) goto skiphtr; skip0: EveWrite(eve, "R5"); /* read heater */ FSM_NEXT me->htr = OiGetFlt(eve, 1, NULL); - if (!me->gas < 0) goto skipgas; + skiphtr: + if (me->gasMode != 2 && me->a < 2) goto skipgas; EveWrite(eve, "R7"); /* read gas flow */ FSM_NEXT - me->coldvalve = OiGetFlt(eve, 1, NULL); + me->gas = OiGetFlt(eve, 1, NULL); skipgas: me->eve.value = me->t[me->sampleChan]; + EveLog(eve); FSM_END } /*----------------------------------------------------------------------------*/ -static int ItcStart(long pc, ItcDriv *me) { +static long ItcStart(long pc, ItcDriv *me) { Eve *eve=&me->eve; FSM_BEGIN @@ -190,7 +198,7 @@ static int ItcStart(long pc, ItcDriv *me) { FSM_END } /*----------------------------------------------------------------------------*/ -static int ItcSetTemp(long pc, ItcDriv *me) { +static long ItcSetTemp(long pc, ItcDriv *me) { Eve *eve=&me->eve; pEVControl evc=eve->evc; float fld; @@ -219,9 +227,10 @@ static int ItcSetTemp(long pc, ItcDriv *me) { OiSet(eve, "T", evc->fTarget, me->dig[me->controlChan]); /* set point */ FSM_NEXT a = 1; - if (me->gas == 2) a = 3; + if (me->gasMode == 2) a = 3; if (me->h == me->controlChan && me->a == a) goto skipa; - if (me->gas == 2) { + me->htrMode = 2; /* heater auto */ + if (me->gasMode == 2) { EveWrite(eve, "A3"); /* auto gas & heater */ } else { EveWrite(eve, "A1"); /* auto heater */ @@ -241,6 +250,74 @@ static int ItcSetTemp(long pc, ItcDriv *me) { quit: FSM_END } +/*----------------------------------------------------------------------------*/ +static long ItcSetGas(long pc, void *obj) { + ItcDriv *me = obj; + Eve *eve=&me->eve; + pEVControl evc=eve->evc; + float fld; + float step; + float ramp; + char buf[4]; + SConnection *pCon; + int a; + + FSM_BEGIN + EveWrite(eve, "C3"); + FSM_NEXT + if (me->gasMode != 1) { + EvePrintf(eve, eError, "gasMode must be set to manual"); + goto quit; + } + FSM_NEXT + if (me->a == 2) { + EveWrite(eve, "A0"); + } else if (me->a == 3) { + EveWrite(eve, "A1"); + } else { + goto skipmode; + } + FSM_NEXT + skipmode: + OiSet(eve, "G", me->gas, 1); /* cold valve setting */ + FSM_NEXT + EveWrite(eve, "C0"); + FSM_NEXT + me->remote = 0; + quit: + FSM_END +} +/*----------------------------------------------------------------------------*/ +static long ItcSetHtr(long pc, void *obj) { + ItcDriv *me = obj; + Eve *eve=&me->eve; + pEVControl evc=eve->evc; + float fld; + float step; + float ramp; + char buf[4]; + SConnection *pCon; + int a; + + FSM_BEGIN + EveWrite(eve, "C3"); + FSM_NEXT + if (me->htrMode != 1) { + EvePrintf(eve, eError, "htrMode must be set to manual"); + goto quit; + } + if (me->a == 0) goto skipmode; + EveWrite(eve, "A0"); + FSM_NEXT + skipmode: + OiSet(eve, "O", me->htr, 1); /* manual heater setting */ + FSM_NEXT + EveWrite(eve, "C0"); + FSM_NEXT + me->remote = 0; + quit: + FSM_END +} /*------------------------------------------------------------------------*/ pEVControl ItcMakeEVC(SConnection *pCon, int argc, char *argv[]) { /* args: @@ -256,6 +333,8 @@ pEVControl ItcMakeEVC(SConnection *pCon, int argc, char *argv[]) { me = evc->pDriv->pPrivate; me->sampleChan = 1; + me->gasMode = 1; + me->htrMode = 1; eve=&me->eve; eve->run = (FsmFunc)ItcSetTemp; diff --git a/lcdriv.c b/lcdriv.c index 5832cf9..c128309 100644 --- a/lcdriv.c +++ b/lcdriv.c @@ -32,12 +32,13 @@ typedef struct { Eve eve; float t[4]; /* set t. & 3 temperatures */ int dig[4]; /* format for these */ - float coldvalve; - int gas; + float gas; int remote; int hot; } LcDriv; +static long LcSetGas(long pc, void *obj); + /*----------------------------------------------------------------------------*/ #define A EVE_ACTPAR #define L EVE_LOGPAR @@ -52,7 +53,7 @@ void LcPars(LcDriv *me, EveParArg *arg) { sprintf(fmt, "%%.%df\tK", me->dig[3]); EveFloatPar(arg, "t3", &me->t[3], fmt, usInternal, (me->dig[3] >= 0) * A + L); - EveFloatPar(arg, "coldvalve", &me->coldvalve, "%.1f\t%%", usInternal, A + L); + EveFloatCmd(arg, "gas", &me->gas, "%.1f\t%%", LcSetGas, usUser, A + L); EveIntPar(arg, "dig1", &me->dig[1], usUser, S); EveIntPar(arg, "dig2", &me->dig[2], usUser, S); @@ -95,10 +96,10 @@ static int LcRead(long pc, LcDriv *me) { EveWrite(eve, "X"); FSM_NEXT LcStatus(me); /* check for errors */ - if (!me->remote) goto skiprmt; - EveWrite(eve, "C0"); - me->remote = 0; - FSM_NEXT +// if (!me->remote) goto skiprmt; +// EveWrite(eve, "C0"); +// me->remote = 0; +// FSM_NEXT skiprmt: if (me->dig[1] < 0) goto skip1; @@ -117,9 +118,27 @@ static int LcRead(long pc, LcDriv *me) { FSM_NEXT me->t[3] = OiGetFlt(eve, me->dig[3], NULL); skip3: - EveWrite(eve, "R7"); /* read gas flow */ + FSM_END +} +/*----------------------------------------------------------------------------*/ +static long LcSetGas(long pc, void *obj) { + LcDriv *me = obj; + Eve *eve=&me->eve; + pEVControl evc=eve->evc; + float fld; + float step; + float ramp; + char buf[4]; + SConnection *pCon; + int a; + + FSM_BEGIN + if (me->remote) goto skipremote; + EveWrite(eve, "C1"); + FSM_NEXT + skipremote: + OiSet(eve, "G", me->gas, 1); /* cold valve setting */ FSM_NEXT - me->coldvalve = OiGetFlt(eve, 1, NULL); quit: FSM_END } diff --git a/logger.c b/logger.c index 834ab3e..c9ba083 100644 --- a/logger.c +++ b/logger.c @@ -19,16 +19,74 @@ Markus Zolliker, Sept 2004 struct Logger { char *name; - char old[132]; + char old[256]; int period; time_t last; long pos; + Logger *next; }; static char *dir = NULL; +static Logger *vars = NULL; +static Logger *list; +static time_t lastLife = 0; /*--------------------------------------------------------------------------*/ -void LoggerWrite(Logger *log, time_t now, int period, char *value) { +Logger *LoggerFind(char *name) { + Logger *p; + p = list; + while (p != NULL) { + if (0==strcasecmp(name, p->name)) { + return p; + } + p = p->next; + } + return NULL; +} +/*--------------------------------------------------------------------------*/ +char *LoggerGetDir(void) { + char path[256], line[32]; + FILE *fil; + time_t now; + static time_t last; + +#define LASTLOGTXT "#last logging entry at:\n" + + if (dir == NULL) { + dir = IFindOption(pSICSOptions, "LoggerDir"); + snprintf(path, sizeof path, "%s/lastlife.dat", dir); + fil = fopen(path, "r"); + if (fil) { + fgets(line, sizeof line, fil); + if (strcmp(line, LASTLOGTXT) == 0) { + fgets(line, sizeof line, fil); + lastLife = atol(line); + if (lastLife < 1000000000) { + printf("bad lastLife %ld\n", lastLife); + } + } + fclose(fil); + } else { + perror("open read error \n"); + } + } + now = time(NULL); + if (now != last) { + snprintf(path, sizeof path, "%s/lastlife.dat", dir); + fil = fopen(path, "w"); + if (fil) { + fprintf(fil, "%s%ld\n", LASTLOGTXT, now); + fclose(fil); + } else { + printf("can not open %s\n", path); + perror("open write error \n"); + } + last = now; + } + return dir; +} +/*--------------------------------------------------------------------------*/ +int LoggerWrite(Logger *log, time_t now, int period, char *value) { char path[256], stim[32], buf[32]; struct tm *tm; int yday, isdst; @@ -37,7 +95,8 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) { FILE *fil; long pos; - if (dir == NULL) return; + LoggerGetDir(); + if (dir == NULL) return 0; if (now == 0) { printf("now==0\n"); } @@ -46,6 +105,8 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) { tm = localtime(&now); if (tm->tm_yday != yday) { log->period = 0; + } else if (0 == strncmp(value, log->old, sizeof(log->old))) { + return 0; } log->last = now; snprintf(path, sizeof path, "%s/%s/", dir, log->name); @@ -56,14 +117,14 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) { fil = fopen(path, "r+"); if (fil == NULL) { /* create new file */ fil = fopen(path, "w+"); - if (fil == NULL) return; + if (fil == NULL) return 0; fputs(stim, fil); } else { /* check if file is actual */ fgets(buf, sizeof buf, fil); if (0 != strncmp(buf, stim, 11)) { fclose(fil); fil=fopen(path, "w+"); /* overwrite old logfile */ - if (fil == NULL) return; + if (fil == NULL) return 0; fputs(stim, fil); } else { fseek(fil, 0, SEEK_END); /* set position to end */ @@ -76,16 +137,17 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) { } else { buf[0]='\0'; } + /* if (log->pos > 0) { fseek(fil, log->pos, SEEK_SET); } log->pos = ftell(fil); + */ strftime(stim, sizeof stim,"%H:%M:%S", tm); fprintf(fil, "%s\t%s%s\n", stim, value, buf); - if (0 != strncmp(value, log->old, sizeof(log->old)) || buf[0]!='\0') { /* value has changed */ - log->pos = ftell(fil); /* next time append to the end */ - } - +// if (0 != strncmp(value, log->old, sizeof(log->old)) || buf[0]!='\0') { /* value has changed */ +// log->pos = ftell(fil); /* next time append to the end */ +// } l = strlen(value); if (l >= sizeof(log->old)) { l = sizeof(log->old) - 1; @@ -93,20 +155,13 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) { strncpy(log->old, value, l); log->old[l] = '\0'; fclose(fil); + return 1; } /*--------------------------------------------------------------------------*/ void LoggerKill(Logger *log) { - if (!log) return; + /* we do not really free the logger, it might be reused + for the same variable later. We set the value to undefined */ LoggerWrite(log, time(NULL), 0, ""); - free(log->name); - free(log); -} -/*--------------------------------------------------------------------------*/ -char *LoggerGetDir(void) { - if (dir == NULL) { - dir = IFindOption(pSICSOptions, "LoggerDir"); - } - return dir; } /*--------------------------------------------------------------------------*/ Logger *LoggerMake(char *name, int period) { @@ -114,9 +169,9 @@ Logger *LoggerMake(char *name, int period) { char path[256]; struct stat st; int i; - char *dir; + time_t t; - dir = LoggerGetDir(); + LoggerGetDir(); if (dir == NULL) return NULL; snprintf(path, sizeof path, "%s/%s", dir, name); i = stat(path, &st); @@ -128,41 +183,67 @@ Logger *LoggerMake(char *name, int period) { i = mkdir(path, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH); if (i < 0) return NULL; /* mkdir failed */ } - log = malloc(sizeof *log); - if (log == NULL) return NULL; - log->name = strdup(name); - if (log->name == NULL) { - free(log); - return NULL; + log = LoggerFind(name); /* look if logger already exists */ + if (log == NULL) { + log = malloc(sizeof *log); + if (log == NULL) return NULL; + log->name = strdup(name); + if (log->name == NULL) { + free(log); + return NULL; + } + log->period = 0; + log->old[0] = '\0'; + log->last = 0; + log->pos = 0; + log->next = list; + list = log; + t = time(NULL) -1; + if (lastLife != 0 && lastLife + period < t) { + t = lastLife + period; + } + LoggerWrite(log, t, period, ""); /* value was undefined since last life of server */ } - log->period = 0; - log->old[0] = '\0'; - log->last = 0; - log->pos = 0; - LoggerWrite(log, time(NULL) - 1, period, ""); return log; } /*--------------------------------------------------------------------------*/ +typedef enum { numeric, text } CompType; + typedef struct { SConnection *pCon; + CompType type; time_t step; - time_t t0, tmin, tmax; - time_t tlast; - float ymin, ymax; - float ylast; - long cnt; + time_t tlim; + time_t tmin, tmax, tlast, told; + float ymin, ymax, ylast, yold; + char slast[256]; + char set[256]; } Compressor; static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) { c->pCon = pCon; c->step = step; - c->tmin = -1; + c->tmin = -2; c->tmax = 0; c->tlast = 0; - c->t0 = 0; + c->tlim = 0; + c->told = 0; c->ylast = LOGGER_NAN; } +static void LoggerOutStr(Compressor *c, time_t t, char *str) { + char line[256]; + + /* printf("out %ld %g\n", t, y); */ + if (0 != strcmp(str, c->slast)) { + snprintf(line, sizeof line, "%ld %s\n", t - c->tlast, str); + c->tlast = t; + c->slast[0]='\0'; + strncat(c->slast, str, sizeof c->slast - 1); + SCWrite(c->pCon, line, eStatus); + } +} + static void LoggerOut(Compressor *c, time_t t, float y) { char line[80]; @@ -175,94 +256,118 @@ static void LoggerOut(Compressor *c, time_t t, float y) { snprintf(line, sizeof line, "%ld %g\n", t - c->tlast, y); } /* printf("-%s\n", line); */ - c->cnt--; c->tlast = t; SCWrite(c->pCon, line, eStatus); } } -static void LoggerSum(Compressor *c) { - if (c->tmin < 0 || c->tmin==0 && c->tmax==0) { - /* printf("nos %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */ - LoggerOut(c, c->t0, LOGGER_NAN); - c->tmin = -1; - } else { - /* printf("sum %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */ - if (c->tmin > c->tmax) { - if (c->tmax >= c->t0) { +static void LoggerPut(Compressor *c, time_t t, char *value) { + char *p; + double y; + + if (c->type == numeric) { + if (t == 0) { /* finish */ + t = c->tlim + 3 * c->step; + y = 0; + } else { + y = strtod(value, &p); + if (p == value) { + y = LOGGER_NAN; + } else { + if (y == LOGGER_NAN) y *= 1.0000002; + } + } + /* printf("put %ld %g\n", t, y); */ + if (c->tlim == 0) goto first; + if (t >= c->tlim) { + c->tlim += c->step; + if (c->tmin > c->tmax) { LoggerOut(c, c->tmax, c->ymax); - } - LoggerOut(c, c->tmin, c->ymin); - } else if (c->tmin < c->tmax) { - if (c->tmin >= c->t0) { + c->ymax = c->ymin; + c->tmax = c->tmin; + } else { LoggerOut(c, c->tmin, c->ymin); + if (c->tmin == c->tmax) goto first; + c->ymin = c->ymax; + c->tmin = c->tmax; } - LoggerOut(c, c->tmax, c->ymax); - } else { - LoggerOut(c, c->tmax, c->ymax); + if (t >= c->tlim) { + LoggerOut(c, c->tmin, c->ymin); + if (t >= c->tlim + c->step) { + LoggerOut(c, c->told, c->yold); + } + goto first; + } + } + if (y <= c->ymin) { + c->ymin = y; + c->tmin = t; + } else if (y > c->ymax) { + c->ymax = y; + c->tmax = t; } - if (c->ylast != LOGGER_NAN) { - c->ymin = c->ylast; - c->ymax = c->ylast; - c->tmin = 0; - c->tmax = 0; - } else { - c->tmin = -1; - } - /* printf("end %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */ + c->yold = y; + c->told = t; + return; + first: + c->tlim = t + 2 * c->step; + c->tmin = t; + c->tmax = t; + c->ymin = y; + c->ymax = y; + return; + } else if (c->type == text) { + if (t != 0) LoggerOutStr(c, t, value); } } - -static void LoggerPut(Compressor *c, time_t t, float y) { - /* printf("put %ld %g\n", t, y); */ - if (t >= c->t0 + c->step) { - LoggerSum(c); - c->t0 = t; - } - if (y == LOGGER_NAN) return; - if (c->tmin < 0) { - c->tmin = t; - c->tmax = t; - c->ymin = y; - c->ymax = y; - } else if (y <= c->ymin) { - c->ymin = y; - c->tmin = t; - } else if (y >= c->ymax) { - c->ymax = y; - c->tmax = t; - } -} /*--------------------------------------------------------------------------*/ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { - time_t from, to, step, xs, lastx, now; + time_t from, to, step, xs, lastt, now; char *p; int i, l, yday, iret, loss; - time_t tim, tr; + int inRange; + time_t t, startim; struct tm tm; - char path[256], line[80]; + char stim[32], path[256], line[256], lastval[256]; char *lin, *val, *stp; FILE *fil; Compressor c; float yy, lasty; + Logger *log; - if (argc < 4) { - SCWrite(pCon, "illegal number of arguments", eError); - return 0; + if (argc < 2) goto illarg; + strtolower(argv[1]); + if (strcmp(argv[1], "vars") == 0) { /* default variables on a graph */ + if (vars == NULL) { + vars = LoggerMake("vars", 1); + if (vars == NULL) return 0; + } + Arg2Text(argc-2, argv+2, line, sizeof line); + LoggerWrite(vars, time(NULL), 1, line); + SCSendOK(pCon); + return 1; } + argtolower(argc, argv); + if (argc < 4) goto illarg; now = time(NULL); from = strtol(argv[1], &p, 0); /* unix time, not year 2038 safe */ if (p == argv[1]) goto illarg; to = strtol(argv[2], NULL, 0); if (p == argv[2]) goto illarg; - step = strtol(argv[3], NULL, 0); + if (strcmp(argv[3],"text") == 0) { /* non-numeric values */ + step = 1; + c.type = text; + } else { + step = strtol(argv[3], NULL, 0); + c.type = numeric; + } if (p == argv[3]) goto illarg; if (from <= 0) from += now; if (to <= 0) to += now; if (step <= 0) step = 1; - dir = LoggerGetDir(); + LoggerGetDir(); if (dir == NULL) { SCWrite(pCon, "LoggerDir not found", eError); return 0; @@ -270,23 +375,37 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData, loss = 0; for (i=4; i= tim) { - if (lastx != 0) { - lastx += xs; - while (lastx < tr) { - LoggerPut(&c, lastx, lasty); - lastx += xs; + t=mktime(&tm); + if (!inRange) { + if (t < startim) { + lastval[0]='\0'; + strncat(lastval, val, sizeof lastval - 1); + lastt = t; + } else { + inRange=1; + if (lastt != 0) { + LoggerPut(&c, lastt, lastval); } + LoggerPut(&c, t, val); } - LoggerPut(&c, tr, yy); + } else { + LoggerPut(&c, t, val); } - lastx = tr; - lasty = yy; } } if (lin == NULL) { @@ -349,17 +467,32 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData, tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; - tim=mktime(&tm); + startim=mktime(&tm); continue; } } - c.ylast = LOGGER_NAN; - LoggerSum(&c); + if (!inRange) { + if (lastt != 0) { + LoggerPut(&c, lastt, lastval); + } + } + LoggerPut(&c, 0, ""); /* finish */ + log = LoggerFind(argv[i]); + if (log) { /* add actual value if it is within range */ + if (to >= log->last) { + c.slast[0]='\0'; + LoggerOutStr(&c, now, log->old); + } + } + if (fil) { + fclose(fil); + fil = NULL; + } } - snprintf(line, sizeof line, "*%d\n", loss); + snprintf(line, sizeof line, "*%d %ld %ld\n", loss, from, to); SCWrite(pCon, line, eStatus); return 1; illarg: - SCWrite(pCon, "illegal argument", eError); + SCWrite(pCon, "illegal argument(s)", eError); return 0; } diff --git a/logger.h b/logger.h index 3b3b4ec..95a26bb 100644 --- a/logger.h +++ b/logger.h @@ -14,6 +14,6 @@ typedef struct Logger Logger; Logger *LoggerMake(char *name, int period); void LoggerKill(Logger *log); -void LoggerWrite(Logger *log, time_t now, int period, char *value); +int LoggerWrite(Logger *log, time_t now, int period, char *value); #endif diff --git a/slsmagnet.c b/slsmagnet.c index 3bbefc5..b42d1fe 100644 --- a/slsmagnet.c +++ b/slsmagnet.c @@ -25,9 +25,7 @@ #include #include - typedef struct __EVDriver *pEVDriver; - -#include +#include "evdriver.h" #include #include