- extended evcontroller

- remote objects
- new ev drivers for oxford IPS,ITC,ILM and LC
M.Z.
This commit is contained in:
cvs
2004-11-17 11:32:05 +00:00
parent 2a93216346
commit aa9ab52528
26 changed files with 3772 additions and 879 deletions

1008
eve.c Normal file

File diff suppressed because it is too large Load Diff

137
eve.h Normal file
View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------
eve.h
extended environment controller utilities
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------*/
#ifndef EVE_H
#define EVE_H
#include "fsm.h"
#include "evcontroller.h"
#include "rs232controller.h"
typedef enum { idleState, readState, expectState, lostState } EveState;
typedef struct EveParArg EveParArg;
typedef struct EvePar EvePar;
/* the parameter definition function may call any parameter function (see below) */
typedef void (*EveParDef)(void *private, EveParArg *arg);
typedef int (*EveSubCmd)(SConnection *pCon, pEVControl evc, int argc, char *argv[]);
/* Eve must always be the first member of the EVCs private struct */
typedef struct Eve {
EveParDef pardef;
rs232 *ser;
Fsm *task; /* a pointer to the task */
FsmFunc todo;
FsmFunc run;
FsmFunc read;
int hwstate;
pEVControl evc;
int errCode; /* error code of last operation. not changed on success */
int verbose;
EveState state;
time_t cmdtime;
float value;
int lost;
int syntax; /* not used in Eve, may be used by the driver. used by OiConn */
char cmd[32];
char ans[64];
char version[64];
int (*checkStatus)(void *self, SConnection *pCon); /* original CheckStatus function */
EvePar *par;
int npar;
time_t logtime;
int period;
char errMsg[128];
} Eve;
#define EVE_ACTPAR 1
#define EVE_LOGPAR 2
#define EVE_SAVEPAR 4
/* parameter functions (pfs)
* -------------------------
* there are some restrictions:
*
* - pfs may only be called from within the pardef function
* - the order and number of pfs must not change at runtime
*
* Arguments:
*
* arg: just the arg Argument in pardef
* name: parameter name, must be static and never changed
* (usually a string literal)
* value: a pointer to the corr. member of the drivers private struct
* fmt: a format. if it contains a blank, the content after the blank is
* skipped when not listing
* access: a SICS access mode (usInternal, usMugger, usUser, usSpy)
* flags: the sum of some flags values:
* EVE_ACTPAR: parameter is active
* EVE_LOGPAR: parameter is logged by default
* EVE_SAVEPAR: parameter is saved on sics exit
* maxsize: the maximum size of a fixed size string, or 0 for a dynamic string
* index: the ObPar index
* list: a NULL terminated list of value names
* subcmd: a function for handling the subcommand
*/
void EveFloatPar(EveParArg *arg, char *name, float *value, char *fmt,
int access, int flags);
void EveIntPar(EveParArg *arg, char *name, int *value,
int access, int flags);
void EveStrPar(EveParArg *arg, char *name, char **value, int maxsize,
int access, int flags);
void EveObPar(EveParArg *arg, int index, char *fmt, int flags);
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);
/* a collection of parameters from the standard EVController
* (limits, tolerance, drive handling, out of tolerance handling)
* normally appearing at the top
*/
void EveStdPar(EveParArg *arg);
/* some even more standard values (should always be used)
* appearing at the end of the list
*/
void EveStdParEnd(EveParArg *arg, char *fmt, int targetFlag);
/* return the connection related to the parameter request */
SConnection *EveArgConn(EveParArg *arg);
/* write to the actual (last driving) connection */
int EvePrintf(Eve *eve, int iOut, char *fmt, ...);
void EveWriteError(Eve *eve);
void EveWrite(Eve *eve, char *cmd);
void EveWaitRead(Eve *eve);
int EveHandler(Eve *eve);
int EveIdle(long pc, Eve *eve);
int EveRun(pEVDriver driver, float fVal);
int EveSend(pEVDriver driver, char *pCommand, char *pReply, int iLen);
int EveCheckStatus(void *evcVoid, SConnection *pCon);
EVMode EveGetMode(void *data);
int EveClose(pEVDriver driver);
int EveAlwaysOk(void *data);
int EveDontFix(pEVDriver driver, int iError);
void EveKill(void *pData);
int EveGetError(pEVDriver driver, int *iCode, char *error, int iErrLen);
int EveInit(pEVDriver driver);
pEVDriver MakeEveDriver(int argc, char *argv[], Eve *eve, SConnection *pCon);
int EveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
pEVControl MakeEveEVC(int argc, char *argv[], Eve *eve, SConnection *pCon);
#define EVE_ILL_ANS -3000
#define EVE_FAULT -3001
#define EVE_DEV_CHANGED -3002
#endif

117
fsm.c Normal file
View File

@ -0,0 +1,117 @@
/* ----------------------------------------------------------------------------
fsm.c
a finite state machine within sics
M. Zolliker, Aug 2004
---------------------------------------------------------------------------- */
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "fsm.h"
#define MAXSTACK 8
typedef struct {
long pc;
FsmFunc func;
} StackItem;
struct Fsm {
void *obj;
FsmHandler handler;
long pc;
FsmFunc func;
time_t till;
int pause;
int sp;
StackItem stack[MAXSTACK];
};
static Fsm *fsm = NULL;
void FsmWait(long delay) {
assert(fsm);
fsm->till = time(NULL) + delay;
}
int FsmTaskHandler(Fsm *this) {
long line;
if (this->pause) {
this->handler(this->obj);
return 1;
}
if (this->pc >= 0) { /* this->pc < 0 means stop current function */
if (this->till != 0) {
if (time(NULL) < this->till) return 1; /* wait */
this->till = 0;
}
if (this->handler(this->obj) == 0) {
return 1; /* wait for answer */
}
fsm = this;
this->pc = this->func(this->pc, this->obj);
fsm = NULL;
}
if (this->pc <= 0) {
if (this->sp == 0) return 0;
this->sp--;
this->pc = this->stack[this->sp].pc;
this->func = this->stack[this->sp].func;
}
return 1;
}
void FsmKill(void *data) {
free(data);
}
Fsm *FsmStartTask(void *obj, FsmHandler handler, FsmFunc func) {
Fsm *new;
new=malloc(sizeof *new);
new->obj = obj;
new->pc = 0;
new->func = func;
new->handler = handler;
new->sp = 0;
new->till = 0;
return new;
}
int FsmStop(Fsm *this, FsmFunc func) {
int i;
if (this == NULL) this = fsm;
assert(this);
for (i=0; i < this->sp; i++) {
if (func == this->stack[i].func) {
break;
}
}
if (i == this->sp) {
if (func != this->func) return 0;
} else {
this->sp = i;
}
this->pc = -1;
return 1;
}
void FsmPause(Fsm *this, int pause) {
this->pause = pause;
}
long FsmCall(long pc, FsmFunc func) {
assert(fsm);
assert(fsm->sp < MAXSTACK);
fsm->stack[fsm->sp].pc = pc;
fsm->stack[fsm->sp].func = fsm->func;
fsm->sp++;
fsm->func = func;
fsm->pc = 0;
return fsm->func(fsm->pc, fsm->obj);
}

66
fsm.h Normal file
View File

@ -0,0 +1,66 @@
/* ----------------------------------------------------------------------------
fsm.h
a finite state machine
M. Zolliker, Aug 2004
---------------------------------------------------------------------------- */
#ifndef FSM_H
#define FSM_H
typedef struct Fsm Fsm;
typedef long (*FsmFunc)(long pc, void *obj);
/* the prototype for a task function
a task function body has the following form:
int Func(long pc, Object *obj) {
<declarations>
BEGIN
...
RETURN
}
The ellipsis might be replaced by any code containing fsm macros.
Loops and conditional statements containing fsm macros are not
allowed, goto statements may be used instead.
*/
#define FSM_BEGIN switch (pc) { default:
#define FSM_END fsm_quit: return 0; }
/* fsm macros: */
#define FSM_NEXT return __LINE__; case __LINE__:
/* waiting for response */
#define FSM_WAIT(DELTA) FsmWait(DELTA); return __LINE__; case __LINE__:
/* waiting DELTA seconds */
#define FSM_CALL(FUNC) return FsmCall(__LINE__, (FsmFunc)FUNC); case __LINE__:
/* call a task subfunction */
typedef int (*FsmHandler)(void *obj);
/* the prototype for the handler. Should return 0 when waiting for an answer
or 1 when result is o.k. */
Fsm *FsmStartTask(void *obj, FsmHandler handler, FsmFunc func);
/* start a task and return a pointer to it */
int FsmTaskHandler(Fsm *task);
/* this is the task handler.
the argument should be the pointer obtained from FsmStartTask
returns 0 when finished, 1 when still running */
int FsmStop(Fsm *task, FsmFunc func);
/* stop a function. returns to the caller next time */
void FsmPause(Fsm *this, int pause);
/* pause=1: pause task, pause=0: continue task */
long FsmCall(long pc, FsmFunc func);
void FsmWait(long delay);
/* these functions are used in fsm macros and must not be called directly */
#endif

145
ilmdriv.c Normal file
View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------
ilmdriv.c
Driver for the Oxford Instruments ILM503/ILM4 temperature controller
and for the Oxford lambda controller
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include <servlog.h>
#include <sicsvar.h>
#include <evdriver.i>
#include <rs232controller.h>
#include "oicom.h"
#include "fsm.h"
typedef struct {
Eve eve;
float lev2, lev3;
int cod1, cod2, cod3;
} IlmDriv;
char *fmts[10]={"unused", "%.1f\t%% N2", "%.1f\t%% He","%.1f\t%% He","",
"","","","","error"};
/*----------------------------------------------------------------------------*/
#define A EVE_ACTPAR
#define L EVE_LOGPAR
#define S EVE_EVE_SAVEPAR
void IlmPars(IlmDriv *me, EveParArg *arg) {
EveFloatPar(arg, "chan2", &me->lev2, fmts[me->cod2],
usInternal, (me->cod2 > 0) * A + L);
EveFloatPar(arg, "chan3", &me->lev2, fmts[me->cod3],
usInternal, (me->cod3 > 0) * A + L);
EveStdParEnd(arg, fmts[me->cod1], A+L);
}
/*----------------------------------------------------------------------------*/
void IlmStatus(IlmDriv *me) {
char *ans;
int *code;
Eve *eve=&me->eve;
int i;
if (eve->state != readState) return;
ans=eve->ans;
code=&eve->errCode;
if (ans[0] != 'X' || ans[4] != 'S' || ans[11] != 'R') {
EvePrintf(eve, eError, "illegal status response");
*code = EVE_FAULT;
return;
}
for (i=1; i<3; i++) {
if (ans[i]<'0' || ans[i] > '9') ans[i]='9';
}
me->cod1 = ans[1]-'0';
me->cod2 = ans[2]-'0';
me->cod3 = ans[3]-'0';
return;
}
/*----------------------------------------------------------------------------*/
static int IlmRead(long pc, IlmDriv *me) {
Eve *eve=&me->eve;
FSM_BEGIN
EveWrite(eve, "X");
FSM_NEXT
IlmStatus(me); /* check for errors */
EveWrite(eve, "R1"); /* read sensor 1 */
FSM_NEXT
me->eve.value = OiGetFlt(eve, 1, NULL);
if (me->cod2 == 0) goto skip2;
EveWrite(eve, "R2"); /* read sensor 1 */
FSM_NEXT
me->lev2 = OiGetFlt(eve, 1, NULL);
skip2:
if (me->cod3 == 0) goto skip3;
EveWrite(eve, "R3"); /* read sensor 1 */
FSM_NEXT
me->lev3 = OiGetFlt(eve, 1, NULL);
skip3:
FSM_END
}
/*----------------------------------------------------------------------------*/
static int IlmStart(long pc, IlmDriv *me) {
Eve *eve=&me->eve;
FSM_BEGIN
EveWrite(eve, "V");
FSM_NEXT
if (0 == strncmp(eve->version, "ILM", 3)) {
me->eve.syntax = 0;
} else {
EvePrintf(eve, eError, "unknown level meter version: %s", eve->version);
goto quit;
}
EvePrintf(eve, eStatus, "connected to %s", eve->version);
FSM_CALL(IlmRead);
quit:
FSM_END
}
/*------------------------------------------------------------------------*/
pEVControl IlmMakeEVC(SConnection *pCon, int argc, char *argv[]) {
/* args:
temperature ilm <rs232>
<host> <port>
*/
Eve *eve;
pEVControl evc;
IlmDriv *me = NULL;
evc = MakeEveEVC(argc, argv, calloc(1, sizeof *me), pCon);
if (!evc) return NULL;
me = evc->pDriv->pPrivate;
eve=&me->eve;
eve->run = NULL; /* no run possible */
eve->read = (FsmFunc)IlmRead;
eve->pardef = (EveParDef)IlmPars;
eve->todo = (FsmFunc)IlmStart;
eve->task = FsmStartTask(me, (FsmHandler)OiHandler, (FsmFunc)EveIdle);
evc->pEnvir->IsInTolerance = EveAlwaysOk;
return evc;
}

1137
ipsdriv.c

File diff suppressed because it is too large Load Diff

272
itcdriv.c Normal file
View File

@ -0,0 +1,272 @@
/*---------------------------------------------------------------------------
itcdriv.c
Driver for the Oxford Instruments ITC503/ITC4 temperature controller
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <math.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include <servlog.h>
#include <sicsvar.h>
#include <evdriver.i>
#include <rs232controller.h>
#include "oicom.h"
#include "fsm.h"
typedef struct {
Eve eve;
float t[4]; /* temperatures (0 unused) */
int dig[4]; /* format for these */
float htr;
float coldvalve;
int sampleChan;
int controlChan;
int gas;
int remote;
int h; /* actual heater channel */
int a; /* actual auto mode */
} ItcDriv;
/*----------------------------------------------------------------------------*/
#define A EVE_ACTPAR
#define L EVE_LOGPAR
#define S EVE_SAVEPAR
void ItcPars(ItcDriv *me, EveParArg *arg) {
char fmt[8]="";
int i;
int flag;
char *ti[4] = {"setp","t1","t2","t3"};
EveStdPar(arg);
flag = me->controlChan != 0 && fabsf(me->eve.evc->fTarget - me->t[0]) > 9e-4;
sprintf(fmt, "%%.%df\tK", me->dig[me->controlChan]);
EveFloatPar(arg, ti[0], &me->t[0], fmt, usInternal, flag*A + L);
for (i=1; i<=3; i++) {
flag = (me->dig[i] >= 0) && (me->sampleChan != i);
sprintf(fmt, "%%.%df\tK", me->dig[i]);
EveFloatPar(arg, ti[i], &me->t[i], fmt, usInternal, flag*A + L);
}
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);
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]);
EveStdParEnd(arg, fmt, A+L);
}
/*----------------------------------------------------------------------------*/
void ItcStatus(ItcDriv *me) {
char *ans;
int *code;
Eve *eve=&me->eve;
if (eve->state != readState) return;
ans=eve->ans;
code=&eve->errCode;
if (ans[0] != 'X' ||
ans[2] != 'A' ||
ans[4] != 'C' ||
ans[6] != 'S') {
EvePrintf(eve, eError, "illegal status response");
*code = EVE_FAULT;
return;
}
me->a = ans[3] - '0';
if (ans[9] == 'H') {
me->h = ans[10] - '0';
} else {
me->h = me->controlChan;
}
if (ans[6] != '3' && me->remote == 2) {
EvePrintf(eve, eError, "ITC switched to local");
*code = EVE_FAULT;
me->remote = 1;
return;
}
}
/*----------------------------------------------------------------------------*/
static int ItcRead(long pc, ItcDriv *me) {
Eve *eve=&me->eve;
char *p;
int l;
FSM_BEGIN
EveWrite(eve, "X");
FSM_NEXT
ItcStatus(me); /* check for errors */
if (!me->remote) goto skiprmt;
EveWrite(eve, "C0");
me->remote = 0;
FSM_NEXT
skiprmt:
if (me->dig[1] < 0) goto skip1;
EveWrite(eve, "R1"); /* read sensor 1 */
FSM_NEXT
me->t[1] = OiGetFlt(eve, me->dig[1], &me->dig[1]);
skip1:
if (me->dig[2] < 0) goto skip2;
EveWrite(eve, "R2"); /* read sensor 2 */
FSM_NEXT
me->t[2] = OiGetFlt(eve, me->dig[2], &me->dig[2]);
skip2:
if (me->dig[3] < 0) goto skip3;
EveWrite(eve, "R3"); /* read sensor 3 */
FSM_NEXT
me->t[3] = OiGetFlt(eve, me->dig[3], &me->dig[3]);
skip3:
me->eve.value = me->t[me->sampleChan];
if (me->controlChan == 0 || me->a) {
me->t[0] = me->eve.evc->fTarget;
goto skip0;
}
EveWrite(eve, "R0"); /* read control T */
FSM_NEXT
me->t[0] = OiGetFlt(eve, me->dig[me->controlChan], NULL);
skip0:
EveWrite(eve, "R5"); /* read heater */
FSM_NEXT
me->htr = OiGetFlt(eve, 1, NULL);
if (!me->gas < 0) goto skipgas;
EveWrite(eve, "R7"); /* read gas flow */
FSM_NEXT
me->coldvalve = OiGetFlt(eve, 1, NULL);
skipgas:
me->eve.value = me->t[me->sampleChan];
FSM_END
}
/*----------------------------------------------------------------------------*/
static int ItcStart(long pc, ItcDriv *me) {
Eve *eve=&me->eve;
FSM_BEGIN
EveWrite(eve, "V");
FSM_NEXT
if (0 == strncmp(eve->version, "ITC503", 6)) {
me->eve.syntax = 3;
} else if (0 == strncmp(eve->version, "ITC4", 4)) {
me->eve.syntax = 0;
} else {
EvePrintf(eve, eError, "unknown temperature controller version: %s", eve->version);
goto quit;
}
EvePrintf(eve, eStatus, "connected to %s", eve->version);
if (me->controlChan == 0 && me->h >= 1 && me->h <= 3) {
me->controlChan = me->h;
}
FSM_CALL(ItcRead);
quit:
FSM_END
}
/*----------------------------------------------------------------------------*/
static int ItcSetTemp(long pc, ItcDriv *me) {
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->controlChan == 0) {
EvePrintf(eve, eError, "no control channel selected");
goto quit;
}
EveWrite(eve, "C3");
FSM_NEXT
if (me->h == me->controlChan) goto skiph;
EveWrite(eve, "A0"); /* heater off */
FSM_NEXT
me->remote = 2;
snprintf(buf, sizeof buf, "H%d", me->controlChan);
EveWrite(eve, buf); /* set heater to channel */
FSM_NEXT
skiph:
OiSet(eve, "T", evc->fTarget, me->dig[me->controlChan]); /* set point */
FSM_NEXT
a = 1;
if (me->gas == 2) a = 3;
if (me->h == me->controlChan && me->a == a) goto skipa;
if (me->gas == 2) {
EveWrite(eve, "A3"); /* auto gas & heater */
} else {
EveWrite(eve, "A1"); /* auto heater */
}
FSM_NEXT
skipa:
EveWrite(eve, "C0");
FSM_NEXT
me->remote = 0;
wait:
pCon = SCLoad(&evc->conn);
eve->hwstate = eve->checkStatus(evc, pCon);
if (eve->hwstate != HWBusy) goto quit;
FSM_CALL(ItcRead);
goto wait;
quit:
FSM_END
}
/*------------------------------------------------------------------------*/
pEVControl ItcMakeEVC(SConnection *pCon, int argc, char *argv[]) {
/* args:
temperature itc <rs232>
<host> <port>
*/
Eve *eve;
pEVControl evc;
ItcDriv *me = NULL;
evc = MakeEveEVC(argc, argv, calloc(1, sizeof *me), pCon);
if (!evc) return NULL;
me = evc->pDriv->pPrivate;
me->sampleChan = 1;
eve=&me->eve;
eve->run = (FsmFunc)ItcSetTemp;
eve->read = (FsmFunc)ItcRead;
eve->pardef = (EveParDef)ItcPars;
eve->todo = (FsmFunc)ItcStart;
eve->task = FsmStartTask(me, (FsmHandler)OiHandler, (FsmFunc)EveIdle);
/* evc->pEnvir->IsInTolerance not changed */
EVCSetPar(evc,"upperlimit",310.0,pCon);
EVCSetPar(evc,"lowerlimit",1.0,pCon);
return evc;
}

184
lcdriv.c Normal file
View File

@ -0,0 +1,184 @@
/*---------------------------------------------------------------------------
lcdriv.c
Driver for the Oxford Instruments Teslatron lambda controller
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include <servlog.h>
#include <sicsvar.h>
#include <evdriver.i>
#include <rs232controller.h>
#include "oicom.h"
#include "fsm.h"
typedef struct {
Eve eve;
float t[4]; /* set t. & 3 temperatures */
int dig[4]; /* format for these */
float coldvalve;
int gas;
int remote;
int hot;
} LcDriv;
/*----------------------------------------------------------------------------*/
#define A EVE_ACTPAR
#define L EVE_LOGPAR
#define S EVE_SAVEPAR
void LcPars(LcDriv *me, EveParArg *arg) {
char fmt[80];
sprintf(fmt, "%%.%df\tK", me->dig[2]);
EveFloatPar(arg, "t2", &me->t[2], fmt, usInternal, (me->dig[2] >= 0) * A + L);
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);
EveIntPar(arg, "dig1", &me->dig[1], usUser, S);
EveIntPar(arg, "dig2", &me->dig[2], usUser, S);
EveIntPar(arg, "dig3", &me->dig[3], usUser, S);
sprintf(fmt, "%%.%df\tmbar", me->dig[1]);
EveStdParEnd(arg, fmt, 0);
}
/*----------------------------------------------------------------------------*/
void LcStatus(LcDriv *me) {
char *ans;
int *code;
Eve *eve=&me->eve;
if (eve->state != readState) return;
ans=eve->ans;
code=&eve->errCode;
if (ans[0] != 'X' ||
ans[2] != 'A' ||
ans[4] != 'C' ||
ans[6] != 'S') {
EvePrintf(eve, eError, "illegal status response");
*code = EVE_FAULT;
return;
}
if (ans[6] != '3' && me->remote == 2) {
EvePrintf(eve, eError, "LC switched to local");
*code = EVE_FAULT;
me->remote = 1;
return;
}
}
/*----------------------------------------------------------------------------*/
static int LcRead(long pc, LcDriv *me) {
Eve *eve=&me->eve;
char *p;
int l;
FSM_BEGIN
EveWrite(eve, "X");
FSM_NEXT
LcStatus(me); /* check for errors */
if (!me->remote) goto skiprmt;
EveWrite(eve, "C0");
me->remote = 0;
FSM_NEXT
skiprmt:
if (me->dig[1] < 0) goto skip1;
EveWrite(eve, "R1"); /* read sensor 1 */
FSM_NEXT
me->t[1] = OiGetFlt(eve, me->dig[1], NULL);
me->eve.value = me->t[1];
skip1:
if (me->dig[2] < 0) goto skip2;
EveWrite(eve, "R2"); /* read sensor 2 */
FSM_NEXT
me->t[2] = OiGetFlt(eve, me->dig[2], NULL);
skip2:
if (me->dig[3] < 0) goto skip3;
EveWrite(eve, "R3"); /* read sensor 3 */
FSM_NEXT
me->t[3] = OiGetFlt(eve, me->dig[3], NULL);
skip3:
EveWrite(eve, "R7"); /* read gas flow */
FSM_NEXT
me->coldvalve = OiGetFlt(eve, 1, NULL);
quit:
FSM_END
}
/*----------------------------------------------------------------------------*/
static int LcStart(long pc, LcDriv *me) {
Eve *eve=&me->eve;
FSM_BEGIN
EveWrite(eve, "V");
FSM_NEXT
if (0 == strncmp(eve->version, "TESLATRON", 9)) {
me->eve.syntax = 0;
me->dig[1] = 1;
me->dig[2] = 2;
me->dig[3] = 1;
} else {
EvePrintf(eve, eError, "unknown lambda controller version: %s", eve->version);
goto quit;
}
EvePrintf(eve, eStatus, "connected to %s", eve->version);
FSM_CALL(LcRead);
quit:
FSM_END
}
/*----------------------------------------------------------------------------*/
static int LcSetTemp(long pc, LcDriv *me) {
Eve *eve=&me->eve;
pEVControl evc=eve->evc;
float fld;
float step;
float ramp;
char buf[4];
SConnection *pCon;
FSM_BEGIN
FSM_END
}
/*------------------------------------------------------------------------*/
pEVControl LcMakeEVC(SConnection *pCon, int argc, char *argv[]) {
/* args:
<objectname> lc <rs232>
<host> <port>
*/
Eve *eve;
pEVControl evc;
LcDriv *me = NULL;
evc = MakeEveEVC(argc, argv, calloc(1, sizeof *me), pCon);
if (!evc) return NULL;
me = evc->pDriv->pPrivate;
eve=&me->eve;
eve->run = (FsmFunc)LcSetTemp;
eve->read = (FsmFunc)LcRead;
eve->pardef = (EveParDef)LcPars;
eve->todo = (FsmFunc)LcStart;
eve->task = FsmStartTask(me, (FsmHandler)OiHandler, (FsmFunc)EveIdle);
return evc;
}

352
logger.c Normal file
View File

@ -0,0 +1,352 @@
/*---------------------------------------------------------------------------
logger.c
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <fortify.h>
#include <errno.h>
#include "sics.h"
#include "logger.h"
#define LOGGER_NAN -999999.
struct Logger {
char *name;
char old[132];
int period;
time_t last;
};
static char *dir = NULL;
/*--------------------------------------------------------------------------*/
void LoggerWrite(Logger *log, time_t now, int period, char *value) {
char path[256], stim[32], buf[32];
struct tm *tm;
int yday, isdst;
int l;
int newday;
FILE *fil;
if (dir == NULL) return;
if (now == 0) {
printf("now==0\n");
}
tm = localtime(&log->last);
yday = tm->tm_yday;
tm = localtime(&now);
if (tm->tm_yday != yday) {
log->period = 0;
} else if (0 == strncmp(value, log->old, sizeof(log->old))) { /* value has not changed */
return;
}
log->last = now;
snprintf(path, sizeof path, "%s/%s/", dir, log->name);
l = strlen(path);
strftime(path + l, sizeof path - l, "%m-%d.log", tm);
fil = fopen(path, "a+");
if (fil == NULL) return;
fseek(fil, 0, SEEK_SET);
fgets(buf, sizeof buf, fil);
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S\n", tm);
if (0 != strncmp(buf, stim, 11)) {
fclose(fil);
fil=fopen(path, "w+"); /* overwrite old logfile */
if (fil == NULL) return;
fputs(stim, fil);
} else {
fseek(fil, 0, SEEK_END); /* set position to end */
}
if (period != log->period) {
log->period = period;
snprintf(buf, sizeof buf, "\t%d", period);
} else {
buf[0]='\0';
}
strftime(stim, sizeof stim,"%H:%M:%S", tm);
fprintf(fil, "%s\t%s%s\n", stim, value, buf);
l = strlen(value);
if (l >= sizeof(log->old)) {
l = sizeof(log->old) - 1;
}
strncpy(log->old, value, l);
log->old[l] = '\0';
fclose(fil);
}
/*--------------------------------------------------------------------------*/
void LoggerKill(Logger *log) {
if (!log) return;
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) {
Logger *log, *p;
char path[256];
struct stat st;
int i;
char *dir;
dir = LoggerGetDir();
if (dir == NULL) return NULL;
snprintf(path, sizeof path, "%s/%s", dir, name);
i = stat(path, &st);
if (i >= 0) {
if (((st.st_mode >> 12) & 15) != 4) { /* exists, but is no directory */
return NULL;
}
} else {
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->period = 0;
log->old[0] = '\0';
log->last = 0;
LoggerWrite(log, time(NULL) - 1, period, "");
return log;
}
/*--------------------------------------------------------------------------*/
typedef struct {
SConnection *pCon;
time_t step;
time_t t0, tmin, tmax;
time_t tlast;
float ymin, ymax;
float ylast;
long cnt;
} Compressor;
static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) {
c->pCon = pCon;
c->step = step;
c->tmin = -1;
c->tmax = 0;
c->tlast = 0;
c->t0 = 0;
c->ylast = LOGGER_NAN;
}
static void LoggerOut(Compressor *c, time_t t, float y) {
char line[80];
/* printf("out %ld %g\n", t, y); */
if (y != c->ylast) {
c->ylast = y;
if (y == LOGGER_NAN) {
snprintf(line, sizeof line, "%ld\n", t - c->tlast);
} else {
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) {
LoggerOut(c, c->tmax, c->ymax);
}
LoggerOut(c, c->tmin, c->ymin);
} else if (c->tmin < c->tmax) {
if (c->tmin >= c->t0) {
LoggerOut(c, c->tmin, c->ymin);
}
LoggerOut(c, c->tmax, c->ymax);
} else {
LoggerOut(c, c->tmax, c->ymax);
}
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); */
}
}
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;
char *p;
int i, l, yday, iret, loss;
time_t tim, tr;
struct tm tm;
char path[256], line[80];
char *lin, *val, *stp;
FILE *fil;
Compressor c;
float yy, lasty;
if (argc < 4) {
SCWrite(pCon, "illegal number of arguments", eError);
return 0;
}
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 (p == argv[3]) goto illarg;
if (from <= 0) from += now;
if (to <= 0) to += now;
if (step <= 0) step = 1;
dir = LoggerGetDir();
if (dir == NULL) {
SCWrite(pCon, "LoggerDir not found", eError);
return 0;
}
loss = 0;
for (i=4; i<argc; i++) {
tim = from;
xs = step;
LoggerInit(&c, pCon, step);
c.cnt = (to - from) / step + 1;
lastx = 0;
lasty = LOGGER_NAN;
snprintf(path, sizeof path, "%s/%s/", dir, argv[i]);
l = strlen(path);
fil = NULL;
snprintf(line, sizeof line, "*%s\n", argv[i]);
SCWrite(pCon, line, eStatus);
while (tim <= to) {
tm = *localtime(&tim);
if (fil == NULL || tm.tm_yday != yday) {
yday = tm.tm_yday;
strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
fil = fopen(path, "r");
}
if (fil == NULL) {
lin == NULL;
} else {
do {
lin = fgets(line, sizeof line, fil);
/* printf("%s\n", line); */
if (lin == NULL) break;
p = strchr(line, '\n'); if (p) *p='\0';
p = strchr(line, '#'); if (p) *p='\0';
} while (lin[0] == '\0');
}
if (lin != NULL) {
/* printf(" %s\n", line); */
p = strchr(line, '\t');
if (p) {
*p='\0';
val = p+1;
} else {
val = "";
}
p = strchr(val, '\t');
if (p) {
*p='\0';
stp = val+1;
iret = sscanf(stp, "%ld", &xs);
if (xs < step) {
loss = 1;
xs = step;
}
}
iret = sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
if (iret != 3) {
lin = NULL;
} else {
tm.tm_isdst = -1;
tr=mktime(&tm);
iret = sscanf(val, "%f", &yy);
if (iret <= 0) {
yy = LOGGER_NAN;
} else {
if (yy == LOGGER_NAN) yy *= 1.0000002;
}
if (tr >= tim) {
if (lastx != 0) {
lastx += xs;
while (lastx < tr) {
LoggerPut(&c, lastx, lasty);
lastx += xs;
}
}
LoggerPut(&c, tr, yy);
}
lastx = tr;
lasty = yy;
}
}
if (lin == NULL) {
tm.tm_hour = 24; /* try next day */
tm.tm_min = 0;
tm.tm_sec = 0;
tm.tm_isdst = -1;
tim=mktime(&tm);
continue;
}
}
c.ylast = LOGGER_NAN;
LoggerSum(&c);
}
snprintf(line, sizeof line, "*%d\n", loss);
SCWrite(pCon, line, eStatus);
return 1;
illarg:
SCWrite(pCon, "illegal argument", eError);
return 0;
}

19
logger.h Normal file
View File

@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------
logger.c
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <time.h>
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);
#endif

View File

@ -18,7 +18,9 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
el755driv.o amorscan.o serial.o scontroller.o t_update.o \
t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \
el737hpv2driv.o swmotor2.o ipsdriv.o tricssupport.o
el737hpv2driv.o swmotor2.o tricssupport.o \
oicom.o fsm.o remob.o eve.o logger.o \
ipsdriv.o itcdriv.o ilmdriv.o lcdriv.o
libpsi.a: $(OBJ)
rm -f libpsi.a

128
oicom.c Normal file
View File

@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------
oicom.c
Communication routines for Oxford Instruments equipment
Markus Zolliker, Aug 2004
----------------------------------------------------------------------------
there is no error return value, eve->errCode is used. On success, eve->errCode
is not changed, i.e. an existing errCode is not overwritten.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include "sics.h"
#include "rs232controller.h"
#include "oicom.h"
/*----------------------------------------------------------------------------*/
int OiHandler(Eve *eve) {
int iret, l;
if (availableNetRS232(eve->ser)) {
l = sizeof(eve->ans);
iret = readRS232TillTerm(eve->ser, eve->ans, &l);
if (eve->state < expectState) {
if (iret == 1) {
EvePrintf(eve, eError, "unexpected answer: %s", eve->ans);
}
goto quit;
}
if (iret == 1) {
EvePrintf(eve, -2, "ans: %s", eve->ans);
if (strcmp(eve->ans, "?ck") == 0) {
if (eve->state == lostState) {
EveWrite(eve, "V");
goto quit;
}
} else if (eve->state == lostState) {
goto quit;
} else if (eve->cmd[0] == 'V') {
if (strcmp(eve->ans, eve->version) == 0) {
/* we are still connected with the same device */
} else if (*eve->version == '\0') {
strncat(eve->version, eve->ans, sizeof(eve->version)-1);
} else { /* version (and therefore device) changed */
eve->errCode = EVE_DEV_CHANGED;
eve->state = idleState;
goto error;
}
eve->state = idleState;
goto quit;
} else if (eve->cmd[1] == 'k') { /* ck */
} else if (eve->cmd[0] != eve->ans[0]) {
iret = EVE_ILL_ANS;
}
}
if (iret != 1) {
eve->errCode = iret;
eve->state = idleState;
goto error;
}
eve->state = readState;
} else if (eve->state == expectState) {
if (time(NULL) > eve->cmdtime+60) {
eve->errCode = TIMEOUT;
eve->state = lostState;
}
} else if (eve->state == lostState) {
if (time(NULL) > eve->cmdtime) {
EveWrite(eve, "ck");
eve->state = lostState;
}
}
goto quit;
error:
EveWriteError(eve);
quit:
return EveHandler(eve);
}
double OiGetFlt(Eve *eve, int dig, int *pdig) {
char *endp, *p;
double val;
if (eve->state != readState) {
/* eve->errCode = EVE_ILL_ANS; */
return 0.0;
}
p = strchr(eve->ans, '.');
if (p) {
if (pdig != NULL) {
*pdig = strlen(eve->ans) - (p - eve->ans) - 1;
}
val=strtod(eve->ans+1, &endp);
if (*endp != '\0') {
eve->errCode = EVE_ILL_ANS;
return 0.0;
}
} else {
val=strtol(eve->ans+1, &endp, 10);
if (*endp != '\0') {
eve->errCode = EVE_ILL_ANS;
return 0.0;
}
if (eve->syntax == 0) { /* old style format */
for (; dig > 0; dig--) val=val*0.1;
}
}
return val;
}
void OiSet(Eve *eve, char *cmd, double val, int dig) {
char buf[64];
if (eve->syntax == 0) {
for (;dig>0;dig--) val=val*10;
snprintf(buf, sizeof(buf), "%s%05d", cmd, val);
} else {
snprintf(buf, sizeof(buf), "%s%f", cmd, val);
}
EveWrite(eve, buf);
}

16
oicom.h Normal file
View File

@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------
oicom.h
Communication routines for Oxford Instruments equipment
Markus Zolliker, Aug 2004
----------------------------------------------------------------------------*/
#include "rs232controller.h"
#include "eve.h"
int OiHandler(Eve *eve);
double OiGetFlt(Eve *eve, int dig, int *pdig);
void OiSet(Eve *eve, char *cmd, double val, int dig);

35
psi.c
View File

@ -39,7 +39,6 @@
#include "tdchm.h"
#include "tecsdriv.h"
#include "itc4.h"
#include "ipsdriv.h"
#include "bruker.h"
#include "ltc11.h"
#include "A1931.h"
@ -50,10 +49,13 @@
#include "amorscan.h"
#include "serial.h"
#include "fomerge.h"
#include "remob.h"
#include "tricssupport.h"
static pSite sitePSI = NULL;
int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]);
/*----------------------------------------------------------------------*/
static void AddPsiCommands(SicsInterp *pInter){
AddCommand(pInter,"MakeRuenBuffer",InitBufferSys,NULL,NULL);
@ -77,6 +79,8 @@ static void AddPsiCommands(SicsInterp *pInter){
AddCommand(pInter,"MakePSDFrame",MakeFrameFunc,NULL,NULL);
AddCommand(pInter,"SerialInit",SerialInit,NULL,NULL);
AddCommand(pInter,"InstallFocusMerge",InstallFocusMerge,NULL,NULL);
AddCommand(pInter,"Remob",RemobCreate,NULL,NULL);
AddCommand(pInter,"Graph",LoggerGraph,NULL,NULL);
/*
AddCommand(pInter,"MakeDifrac",MakeDifrac,NULL,NULL);
*/
@ -317,8 +321,6 @@ static void ConfigureController(char *name, pEVControl pNew,
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
if(strcmp(name,"tecs") == 0){
TecsCustomize(pCon, pNew);
} else if(strcmp(name,"ips") == 0){
IpsCustomize(pCon, pNew);
} else if(strcmp(name,"euro") == 0){
EVCSetPar(pNew,"upperlimit",750.0,pCon);
EVCSetPar(pNew,"lowerlimit",15.0,pCon);
@ -335,7 +337,13 @@ static void ConfigureController(char *name, pEVControl pNew,
}
/*-------------------------------------------------------------------*/
extern pEVDriver CreateSLSDriv(int argc, char *argv[]);
pEVControl IpsMakeEVC(SConnection *pCon, int argc, char *argv[]);
pEVControl ItcMakeEVC(SConnection *pCon, int argc, char *argv[]);
pEVControl IlmMakeEVC(SConnection *pCon, int argc, char *argv[]);
pEVControl LcMakeEVC(SConnection *pCon, int argc, char *argv[]);
/*------------------------------------------------------------------*/
static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
SConnection *pCon,
int argc, char *argv[]){
@ -374,16 +382,13 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
}
}
} else if(strcmp(argv[3],"ips") == 0) {
checkError = 1;
pDriv = CreateIpsDriver(argc-4,&argv[4]);
if(pDriv){
pNew = CreateEVController(pDriv,argv[2],&status);
if(pNew != NULL){
AddCommand(pSics,argv[2],IpsWrapper,DeleteEVController,
pNew);
commandInstalled = 1;
}
}
return IpsMakeEVC(pCon, argc-2, argv+2); /* we should organize all devices like this M.Z. */
} else if(strcmp(argv[3],"itc") == 0) {
return ItcMakeEVC(pCon, argc-2, argv+2);
} else if(strcmp(argv[3],"ilm") == 0) {
return IlmMakeEVC(pCon, argc-2, argv+2);
} else if(strcmp(argv[3],"lc") == 0) {
return LcMakeEVC(pCon, argc-2, argv+2);
} else if(strcmp(argv[3],"bruker") == 0){
checkError = 1;
pDriv = CreateBrukerDriver(argc-4,&argv[4]);
@ -439,6 +444,10 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
if(pDriv != NULL){
pNew = CreateEVController(pDriv,argv[2],&status);
}
} else {
sprintf(pBueffel,"ERROR: %s not recognized as a valid driver type", argv[3]);
SCWrite(pCon,pBueffel,eError);
return NULL;
}
/* if we recognized the driver, check for installation errors */

785
remob.c Normal file
View File

@ -0,0 +1,785 @@
/*-----------------------------------------------------------------------
remob.c
implements remote driveable objects living on an other sics server
M. Zolliker July 04
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <tcl.h>
#include "fortify.h"
#include "sics.h"
#include "devexec.h"
#include "remob.h"
#include "splitter.h"
#include "status.h"
#include "servlog.h"
#include "site.h"
/*-------------------------------------------------------------------------*/
#define INTERRUPTMODE 0
#define ACCESSCODE 1
/*------------------------------------------------------------------------ */
typedef struct Remob Remob;
typedef struct RemServer {
pObjectDescriptor desc;
char *name;
char *host;
int port;
char *user;
char *pass;
mkChannel *chan;
int incomplete;
char line[256];
Remob *objList;
int matchMap;
int timeout;
int taskActive;
SCStore conn;
} RemServer;
struct Remob {
pObjectDescriptor desc;
char *name;
ObPar *ParArray;
pIDrivable pDrivInt;
pICallBack pCall;
RemServer *server;
int status;
Remob *next;
};
typedef struct {
float fVal;
char *pName;
} RemobCallback;
typedef struct {
char *pName;
SConnection *pCon;
} RemobInfo;
/*-------------------------------------------------------------------------*/
static char *StartsWith(char *line, char *name) {
/* if line does not start with name, return NULL
else return a pointer to the next non-white space character
*/
char *str;
int l;
l = strlen(name);
if (0 != strncmp(line, name, l)) return NULL;
str = line + l;
while (*str == ' ') {
str++;
}
return str;
}
/*-------------------------------------------------------------------------*/
static int RemWrite(RemServer *remserver, char *line) {
if (remserver->chan) {
/* printf("> %s\n", line); */
return NETWrite(remserver->chan, line, strlen(line));
} else {
return -1;
}
}
/*-------------------------------------------------------------------------*/
static int RemRead(RemServer *remserver, long tmo) {
int iRet;
if (remserver->chan == NULL) return 0; /* no data */
iRet = NETReadTillTermNew(remserver->chan, tmo, "\n",
remserver->line+remserver->incomplete, sizeof(remserver->line)-remserver->incomplete);
if (iRet == 0) {
remserver->incomplete = strlen(remserver->line); /* number of chars already received */
return 0; /* timeout */
} else {
remserver->incomplete=0;
}
return iRet;
}
/*-------------------------------------------------------------------------*/
static int RemHandle(RemServer *remserver) {
char *line, *par, *str;
Remob *remob;
/* skip whitespace at the beginning */
line=remserver->line;
while (*line < ' ' && *line != '\0') {
line++;
}
memmove(remserver->line, line, strlen(line));
/* handle drivstat messages */
line = remserver->line;
for (remob = remserver->objList; remob != NULL; remob = remob->next) {
par=StartsWith(line, remob->name);
if (par != NULL) {
if (str = StartsWith(par, "finished")) {
if (*str == '\0') {
remob->status = HWIdle;
} else {
remob->status = HWFault;
}
line[0]='\0';
return 1;
}
if (str = StartsWith(par, "started")) {
remob->status = HWBusy;
line[0]='\0';
return 1;
}
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int RemCopy(RemServer *remserver, SConnection *pCon) {
char buf[256];
if (pCon != NULL && remserver->line[0] != '\0') {
snprintf(buf, sizeof(buf), " %s", remserver->line);
/* snprintf(buf, sizeof(buf), "%s (%s)", remserver->line, remserver->name); */
SCWrite(pCon, buf, eStatus);
}
}
/*-------------------------------------------------------------------------*/
static int RemServerTask(void *data) {
RemServer *remserver=data;
int iRet;
SConnection *pCon;
if (!remserver->taskActive) return 0; /* remove task */
if (RemRead(remserver, 0) <= 0) return 1; /* continue */
/* printf("< %s\n", buf); */
if (RemHandle(remserver)) { /* handle drivstat messages */
return 1;
}
/* forward oll other messages */
pCon = SCLoad(&remserver->conn);
if (pCon) {
RemCopy(remserver, pCon);
}
return 1;
}
/*-------------------------------------------------------------------------*/
static void RemDisconnect(RemServer *remserver) {
if (remserver->chan != NULL) {
NETClosePort(remserver->chan);
free(remserver->chan);
remserver->chan=NULL;
/* printf("disconnected\n"); */
}
}
/*-------------------------------------------------------------------------*/
static void RemConnect(RemServer *remserver) {
int iRet;
char buf[256];
if (!remserver->chan) {
remserver->timeout = 0;
remserver->chan = NETConnect(remserver->host, remserver->port);
if (!remserver->chan) {
return;
}
snprintf(buf, sizeof(buf), "%s %s\ntransact listexe interest\n"
, remserver->user, remserver->pass);
iRet = RemWrite(remserver, buf);
if (iRet < 0) goto close;
iRet = RemRead(remserver, 1000);
while (iRet > 0) { /* eat login response */
if (StartsWith(remserver->line, "TRANSACTIONFINISHED")) {
/* printf("connected\n"); */
return;
}
iRet = RemRead(remserver, 1000);
}
goto close;
}
return;
close:
RemDisconnect(remserver);
return;
}
/*-------------------------------------------------------------------------*/
static int RemTransact(RemServer *remserver, SConnection *pCon, char *cmd, ...) {
/* the variable arguments are for filtering:
"<name", &val get float value named m
"!blabla" skip lines starting with blabla
">" write untreated lines to pCon
*/
char buf[256];
int iRet;
int i, typ;
char *arg, *val, *endp;
float *f;
va_list ap;
int try;
int argMask;
try=2;
if (remserver->timeout) { /* eat old responses */
while (RemRead(remserver, 0) > 0) {
RemHandle(remserver);
}
}
tryagain:
strcpy(buf, "transact ");
strcat(buf, cmd);
strcat(buf,"\n");
RemConnect(remserver);
iRet = RemWrite(remserver, buf);
if (iRet < 0) goto close;
iRet = RemRead(remserver, 2000);
if (iRet <= 0) goto close;
while (!StartsWith(remserver->line, "TRANSACTIONFINISHED")) {
RemHandle(remserver);
va_start(ap, cmd);
arg = va_arg(ap, char *);
argMask=1;
remserver->matchMap = 0;
while (arg != NULL) {
if (*arg == '>') {
RemCopy(remserver, pCon);
} else if (*arg == '<') {
f = va_arg(ap, float *);
val = StartsWith(remserver->line, arg+1);
if (val != NULL) {
val = StartsWith(val, "=");
if (val != NULL) {
*f = strtod(val, &endp);
break;
}
}
} else if (*arg == '!') {
if (StartsWith(remserver->line, arg+1)) {
remserver->matchMap |= argMask;
argMask = argMask*2;
break;
}
} else {
printf("unknown argument in RemTransact: %s\n", arg);
assert(0);
}
arg = va_arg(ap, char *);
}
va_end(ap);
iRet = RemRead(remserver, 2000);
if (iRet <= 0) goto close;
}
return 1;
close:
if (iRet == 0) {
snprintf(buf, sizeof(buf), "ERROR: timeout on %s", remserver->name);
SCWrite(pCon,buf,eError);
remserver->timeout = 1;
return iRet;
}
snprintf(buf, sizeof(buf), "ERROR: no connection to %s", remserver->name);
SCWrite(pCon,buf,eError);
RemDisconnect(remserver);
try--;
if (try>0) goto tryagain;
return iRet;
}
/*-------------------------------------------------------------------------*/
static void *RemobGetInterface(void *pData, int iID) {
Remob *self = pData;
assert(self);
if(iID == DRIVEID) {
return self->pDrivInt;
} else if(iID == CALLBACKINTERFACE) {
return self->pCall;
}
return NULL;
}
/*------------------------------------------------------------------------*/
static int RemobHalt(void *self) {
Remob *remob=self;
RemServer *remserver;
char buf[64];
assert(remob);
remserver = remob->server;
RemConnect(remserver);
snprintf(buf, sizeof(buf), "stopexe %s\n", remob->name);
return RemWrite(remserver, buf);
}
/*--------------------------------------------------------------------------*/
static int RemobLimits(void *self, float fVal, char *error, int iErrLen) {
float fHard;
Remob *remob=self;
assert(remob);
/* check is done one remote server */
return 1;
}
/*---------------------------------------------------------------------------*/
static float RemobGetValue(void *pData, SConnection *pCon) {
Remob *remob=pData;
char buf[80];
float none, value;
int iRet;
assert(remob);
SCSave(&remob->server->conn, pCon);
none = -1.25e6;
value= none;
snprintf(buf, sizeof(buf), "<%s", remob->name);
iRet = RemTransact(remob->server, pCon, remob->name, buf, &value, ">", NULL);
if (iRet <= 0) {
return 0.0;
}
if (value != none) {
return value;
}
snprintf(buf, sizeof(buf), "can not get %s", remob->name);
SCWrite(pCon, buf, eWarning);
return 0.0;
}
/*------------------------------------------------------------------------*/
static int RemobSaveStatus(void *pData, char *name, FILE *fd) {
Remob *self = pData;
char buf[512];
assert(self);
assert(fd);
/*
data is stored on remote server
*/
return 1;
}
/*------------------------------------------------------------------------*/
static int RemobStatus(void *pData, SConnection *pCon) {
Remob *remob=pData;
assert(remob);
SCSave(&remob->server->conn, pCon);
return remob->status;
}
/*---------------------------------------------------------------------------*/
static long RemobRun(void *self, SConnection *pCon, float fNew) {
Remob *remob=self;
float fHard;
int i, iRet, iCode;
char buf[512], sBuf[64];
char pError[132];
Remob *p;
RemServer *remserver;
long lTime;
float fDelta;
remserver = remob->server;
SCSave(&remserver->conn, pCon);
assert(remob);
assert(pCon);
/* check if I'am allowed to move this motor */
if (!SCMatchRights(pCon,(int)ObVal(remob->ParArray,ACCESSCODE))) {
snprintf(buf,sizeof(buf), "ERROR: You are not authorised to run %s",
remob->name);
SCWrite(pCon,buf,eError);
SCSetInterrupt(pCon,eAbortBatch);
return 0;
}
remob->status = HWIdle;
snprintf(buf, sizeof(buf), "run %s %f", remob->name, fNew);
iRet = RemTransact(remserver, pCon, buf, "!ERROR: somebody else", "!ERROR: cannot", ">", NULL);
if (iRet <= 0) return 0;
if (remserver->matchMap & 1) { /* already running, stop first */
remob->status = HWBusy;
snprintf(sBuf, sizeof(sBuf), "stopexe %s", remob->name, fNew);
iRet = RemTransact(remserver, pCon, sBuf, ">", NULL);
if (iRet <= 0) return 0;
while (remob->status == HWBusy) {
iRet = RemRead(remserver, 1000);
if (iRet <= 0) break;
RemCopy(remserver, pCon);
}
iRet = RemTransact(remserver, pCon, buf, ">", NULL);
if (iRet <= 0) return 0;
}
if (remob->status != HWBusy) {
return 0;
}
return OKOK;
}
/*-----------------------------------------------------------------------*/
static void KillInfo(void *pData) {
RemobInfo *self = pData;
assert(self);
if (self->pName) {
free(self->pName);
}
free(self);
}
/*------------------- The CallBack function for interest ------------------*/
static int InterestCallback(int iEvent, void *pEvent, void *pUser) {
RemobCallback *psCall = pEvent;
RemobInfo *pInfo = pUser;
char buf[80];
assert(psCall);
assert(pInfo);
snprintf(buf, sizeof(buf),"%s.position = %f ", pInfo->pName, psCall->fVal);
SCWrite(pInfo->pCon,buf,eValue);
return 1;
}
/*---------------------------------------------------------------------------*/
int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]) {
Remob *remob = pData;
char buf[512];
TokenList *pList = NULL;
TokenList *pCurrent;
TokenList *pName;
int iRet;
int i;
int pos;
float fValue;
long lID;
char *endp;
ObPar *par;
char acce[128], inte[128];
assert(pCon);
assert(pSics);
assert(remob);
argtolower(argc,argv);
SCSave(&remob->server->conn, pCon);
if (argc == 1) {
iRet = RemTransact(remob->server, pCon, argv[0], ">", NULL);
} else if (strcmp(argv[1],"list") == 0) {
snprintf(buf, sizeof(buf), "%s list", remob->name);
snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name);
snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name);
RemTransact(remob->server, pCon, buf, acce, inte, ">", NULL);
snprintf(buf, sizeof(buf), "%s = %.0f", acce+1, ObVal(remob->ParArray,ACCESSCODE));
SCWrite(pCon, buf, eStatus);
snprintf(buf, sizeof(buf), "%s = %.0f", inte+1, ObVal(remob->ParArray,INTERRUPTMODE));
SCWrite(pCon, buf, eStatus);
iRet=1;
} else {
par=ObParFind(remob->ParArray, argv[1]);
if (par != NULL) {
if (argc == 3) {
fValue = strtod(argv[2], &endp);
if (endp == argv[2]) {
snprintf(buf, sizeof(buf), "number expected instead of %s", argv[2]);
SCWrite(pCon, buf, eError);
return 0;
}
iRet = ObParSet(remob->ParArray,argv[0],argv[1],fValue,pCon);
}
if (iRet) {
snprintf(buf, sizeof(buf), "%s.%s = %.0f", argv[0], argv[1], par->fVal);
SCWrite(pCon, buf, eStatus);
}
} else {
pos=snprintf(buf, sizeof(buf), "%s ", remob->name);
for (i=1; i<argc; i++) {
pos+=snprintf(buf+pos, sizeof(buf)-pos, "%s ", argv[i]);
}
iRet = RemTransact(remob->server, pCon, buf, ">", NULL);
}
}
return iRet;
}
/*---------------------------------------------------------------------------*/
int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]) {
RemServer *remserver = pData;
char buf[512];
TokenList *pList = NULL;
TokenList *pCurrent;
TokenList *pName;
int iRet;
int i;
int pos;
float fValue;
long lID;
char *endp;
ObPar *par;
char acce[128], inte[128];
assert(pCon);
assert(pSics);
assert(remserver);
argtolower(argc,argv);
if (argc == 1) {
snprintf(buf, sizeof(buf), "%s = %s:%d", argv[0], remserver->host, remserver->port);
SCWrite(pCon, buf, eStatus);
} else {
pos=0;
for (i=1; i<argc; i++) {
pos+=snprintf(buf+pos, sizeof(buf)-pos, "%s ", argv[i]);
}
iRet = RemTransact(remserver, pCon, buf, ">", NULL);
return iRet;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static void RemobKill(void *self) {
Remob *remob = self;
Remob *p, **last;
assert(remob);
/* remove from object list */
if (remob->server) {
last = &remob->server->objList;
p = *last;
while (p != remob && p !=NULL) {
last = &p->next;
p = p->next;
}
if (p != NULL) {
*last = p->next;
}
remob->next = NULL;
}
if (remob->name) {
free(remob->name);
}
if (remob->pDrivInt) {
free(remob->pDrivInt);
}
if (remob->pCall) {
DeleteCallBackInterface(remob->pCall);
}
/* get rid of parameter space */
if (remob->ParArray) {
ObParDelete(remob->ParArray);
}
/* kill Descriptor */
DeleteDescriptor(remob->desc);
free(remob);
}
/*--------------------------------------------------------------------------*/
static void RemServerKill(void *self) {
RemServer *remserver = self;
assert(remserver);
if (remserver->taskActive) {
remserver->taskActive=0;
/* let the tasker kill me */
return;
}
remserver = (RemServer *)self;
if (remserver->chan) {
RemDisconnect(remserver);
}
DeleteDescriptor(remserver->desc);
if (remserver->name) free(remserver->name);
if (remserver->host) free(remserver->host);
if (remserver->user) free(remserver->user);
if (remserver->pass) free(remserver->pass);
free(remserver);
}
/*-----------------------------------------------------------------------*/
static Remob *RemobInit(char *name, RemServer *remserver) {
Remob *remob, *p;
assert(name);
/* get memory */
remob = (Remob *)malloc(sizeof(Remob));
if(!remob) {
return NULL;
}
/* create and initialize parameters */
remob->ParArray = ObParCreate(2);
if (!remob->ParArray) {
free(remob);
return NULL;
}
ObParInit(remob->ParArray,INTERRUPTMODE,"interruptmode",0.0,usUser);
ObParInit(remob->ParArray,ACCESSCODE,"accesscode",(float)usUser,usMugger);
/* copy arguments */
remob->server = remserver;
remob->name = strdup(name);
/* initialise object descriptor */
remob->desc = CreateDescriptor("Remob");
if (!remob->desc) {
ObParDelete(remob->ParArray);
free(remob);
return NULL;
}
remob->desc->GetInterface = RemobGetInterface;
remob->desc->SaveStatus = RemobSaveStatus;
/* initialise Drivable interface */
remob->pDrivInt = CreateDrivableInterface();
if (!remob->pDrivInt) {
DeleteDescriptor(remob->desc);
ObParDelete(remob->ParArray);
free(remob);
return NULL;
}
remob->pDrivInt->SetValue = RemobRun;
remob->pDrivInt->CheckLimits = RemobLimits;
remob->pDrivInt->CheckStatus = RemobStatus;
remob->pDrivInt->GetValue = RemobGetValue;
remob->pDrivInt->Halt = RemobHalt;
/* initialise callback interface */
remob->pCall = CreateCallBackInterface();
if(!remob->pCall) {
RemobKill(remob);
return NULL;
}
/* check if not yet in object list */
for (p = remserver->objList; p != NULL; p=p->next) {
if (p == remob) break;
}
if (p == NULL) {
remob->next = remserver->objList;
remserver->objList = remob;
}
if (!remserver->taskActive) {
remserver->taskActive = 1;
TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill, remserver, 1);
}
/* done */
return remob;
}
/*-----------------------------------------------------------------------*/
static RemServer *RemServerInit(char *name, char *host, int port, char *user, char *pass) {
RemServer *remserver = NULL;
assert(name);
remserver = malloc(sizeof(RemServer));
if (!remserver) {
return 0;
}
/* initialise object descriptor */
remserver->desc = CreateDescriptor("RemServer");
if (!remserver->desc) {
free(remserver);
return NULL;
}
remserver->taskActive = 0;
remserver->name = strdup(name);
remserver->host = strdup(host);
remserver->port = port;
remserver->user = strdup(user);
remserver->pass = strdup(pass);
remserver->incomplete = 0;
if (!remserver->name ||
!remserver->host ||
!remserver->port ||
!remserver->pass) {
/* no success, clean up */
RemServerKill(remserver);
return NULL;
}
return remserver;
}
/*--------------------------------------------------------------------------
The Factory function for creating a remote driveable object.
Usage:
Remob server serverName host port user pass
Remob new remobName serverName
Remob del remobName (not yet implemented)
Remob del serverName (not yet implemented)
*/
int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]) {
RemServer *remserver = NULL;
Remob *remob = NULL;
char buf[512];
int iD, iRet;
Tcl_Interp *pTcl = (Tcl_Interp *)pSics->pTcl;
assert(pCon);
assert(pSics);
if (argc <= 5) {
argtolower(argc,argv);
} else {
argtolower(5,argv);
}
if (argc == 7 && strcmp(argv[1], "server") == 0) {
remserver = RemServerInit(argv[2], argv[3], atoi(argv[4]), argv[5], argv[6]);
if (!remserver) {
snprintf(buf, sizeof(buf), "Failure to create remote server connection %s", argv[2]);
SCWrite(pCon, buf, eError);
return 0;
}
/* create the interpreter command */
iRet = AddCommand(pSics,argv[2],RemServerAction,RemServerKill,remserver);
if (!iRet) {
snprintf(buf, sizeof(buf),"ERROR: duplicate command %s not created",argv[1]);
SCWrite(pCon,buf,eError);
return 0;
}
return 1;
} else if (argc == 4 && strcmp(argv[1], "new") == 0) {
remserver = FindCommandData(pServ->pSics, argv[3], "RemServer");
if (!remserver) {
snprintf(buf, sizeof(buf), "remote server %s not found", argv[3]);
SCWrite(pCon, buf, eError);
return 0;
}
remob = RemobInit(argv[2], remserver);
if (!remob) {
snprintf(buf, sizeof(buf), "Failure to create remote driveable object %s", argv[1]);
SCWrite(pCon, buf, eError);
return 0;
}
/* create the interpreter command */
iRet = AddCommand(pSics,argv[2],RemobAction,RemobKill,remob);
if (!iRet) {
snprintf(buf, sizeof(buf),"ERROR: duplicate command %s not created",argv[1]);
SCWrite(pCon,buf,eError);
return 0;
}
return 1;
}
snprintf(buf, sizeof(buf),"ERROR: illegal arguments for command remob",argv[1]);
SCWrite(pCon,buf,eError);
}

19
remob.h Normal file
View File

@ -0,0 +1,19 @@
/*--------------------------------------------------------------------------
remote driveable objects
Markus Zolliker July 04
copyright: see implementation file
----------------------------------------------------------------------------*/
#ifndef SICSREM
#define SICSREM
#include "Scommon.h"
/*-------------------------------------------------------------------------*/
int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#endif

View File

@ -42,7 +42,7 @@ foreach dest ($destlist)
endif
end
set items=(TecsServer TecsClient six keep_running cfg)
set items=(TecsServer TecsClient six keep_running)
echo ""
echo " all $items"
@ -70,21 +70,12 @@ if ($this == $0) then
endif
cd $this
set makeit=1
set obj=../../obj/$SICS_VERSION/psi/tecs
foreach dest ($where)
alias get 'set d=$'"d_$dest;"'set t=$'"t_$dest"
get
foreach item ($what)
echo $item D $d T $t
if ($item == cfg) then
if ($makeit) then
make config
set makeit=0
endif
echo tecs $d
rsync -e ssh -rCtv --delete-excluded $obj/cfg $d
else if ("$t" == "$OSTYPE") then
if ("$t" == "$OSTYPE") then
echo $item to $d
rsync -e ssh -vt $obj/$item $d
endif

View File

@ -9,7 +9,7 @@ foreach file ($files)
echo ' $Q -p$(CFGDIR)' >> src/make_crv
echo '' >> src/make_crv
end
echo "all_crv: \" >> src/make_crv
echo "all_crv: dev.list \" >> src/make_crv
foreach file ($files)
set sens=${file:t:s/.inp//}
echo ' $(CFGDIR)'"$sens.crv \" >> src/make_crv

View File

@ -39,6 +39,10 @@ CFGDIR=/afs/psi.ch/project/sinq/common/lib/tecs/cfg/
$(SRC)make_crv: make_crv.tcsh inp/lsc.codes $(ALLINP)
$(SRC)make_crv.tcsh $(SRC)inp/lsc.codes
dev.list:
$(SRC)make_list.tcsh $(CFGDIR)*.cfg > $@
cp $@ $(CFGDIR)
# use target all_crv to make all curves in inp directory
TecsServer: $(SERV_OBJ) $(HARDSUPLIB) $(FORTIFYOBJ)

View File

@ -227,31 +227,38 @@ void StrNLink(StrBuf *buf, char *str, int length) {
void flt_to_char4(double f, char buf[4]) {
double m;
int e, res, ir;
int e;
long res;
m=frexp(f, &e);
e=e+EXP_OFFS;
if (e<0 || m==0) {
res=0; m=0;
m = frexp(f, &e);
e += EXP_OFFS;
if (e < 0 || m == 0) {
res = 0; m = 0;
} else {
if (e>255) {
res=255*TWO_23+(TWO_23-1); /* max. representable number */
if (e > 255) {
res = 255 * TWO_23 + (TWO_23 - 1); /* max. representable number */
} else {
res=e*TWO_23+(int)(0.5+(fabs(m*2)-1.0)*TWO_23);
res = (long)(0.5 + (fabs(m * 2) - 1.0) * TWO_23);
/* here we may think about the case, where m is just a little less than 1.0:
the mantissa part overflows to bit23, but, the result would be o.k., since this
just increases the exponent by one, and the mantissa bits get all zero.
but what happens when e is already 255 ? the next line handles this */
if (res == TWO_23 && e == 255) res--;
res += e * TWO_23;
}
}
buf[0]=res % 256; res=res/256;
buf[1]=res % 256; res=res/256;
buf[2]=res % 256; res=res/256;
if (m<0) {
buf[3]=res-128;
buf[0] = res % 256; res = res / 256;
buf[1] = res % 256; res = res / 256;
buf[2] = res % 256; res = res / 256;
if (m < 0) {
buf[3] = res - 128;
} else {
buf[3]=res;
buf[3] = res;
}
}
double flt_from_char4(char buf[4]) {
int s, i, b0, b1, b2, b3;
long i, b0, b1, b2, b3;
b0=buf[0]; if (b0<0) b0+=256;
b1=buf[1]; if (b1<0) b1+=256;

View File

@ -2195,13 +2195,15 @@ static int xw_read_cursor(xw, mode, posn, ref, pos, key)
/*
* Discard un-handled ButtonPress, KeyPress and MotionNotify events.
*/
if (xw->nofocus) { /* M.Z. */
/* removed M.Z.
if (xw->nofocus) {
while(xw_check_window_event(xw, xw->window, (long)
(ButtonPressMask | PointerMotionMask), &event));
} else {
while(xw_check_window_event(xw, xw->window, (long)
(ButtonPressMask | KeyPressMask | PointerMotionMask), &event));
}
*/
if(xw->bad_device)
return xw_end_cursor(xw, bc, 1);
xw->nofocus=0; /* M.Z. */
@ -2326,9 +2328,10 @@ static int xw_read_cursor(xw, mode, posn, ref, pos, key)
case MotionNotify:
/*
* Discard all but the last MotionNotify event.
*/
*/
while(xw_check_window_event(xw, xw->window, (long)(PointerMotionMask),
&event));
if(xw->bad_device || xw_erase_cursor(xw, bc))
return xw_end_cursor(xw, bc, 1);
last.x = event.xmotion.x;
@ -3548,7 +3551,7 @@ static int xw_next_event(xw, event)
}
/*.......................................................................
* like xw_next_event (see above), but with timeout in decisSecs (M.Z.)
* like xw_next_event (see above), but with timeout in deciSecs (M.Z.)
*/
#ifdef __STDC__
static int xw_next_event_tmo(XWdev *xw, XEvent *event, int tmo_10)

View File

@ -259,18 +259,6 @@ int setrights(int gotolevel) {
} else {
deflevel=2;
}
/*
if (NULL != strstr(instr, "TASP")) {
if (user1[0]=='\0') {
str_copy(user1,"Spy");
str_copy(pswd1,"007");
}
if (user2[0]=='\0') {
str_copy(user2,"Spy");
str_copy(pswd2,"007");
}
}
*/
if (gotolevel==0) gotolevel=deflevel;
if (gotolevel==1) {
if (user1[0]=='\0') {
@ -401,6 +389,7 @@ int main (int argc, char *argv[]) {
int iret, pos;
fd_set mask;
int l, i, j, port, skip, gotolevel, sicslogin;
int savehist = 0;
char buf[128], lbuf[16], ilow[64];
char stdPrompt[128], prompt[256];
char *sim="";
@ -527,6 +516,7 @@ int main (int argc, char *argv[]) {
pos=0;
term_read_hist("six");
savehist = 1;
while (1) {
if (*p=='E') { /* Eager to ... */
@ -589,15 +579,17 @@ int main (int argc, char *argv[]) {
assert(fd==iret);
ERR_P(p=readWrite(fd,1000,0,"status = "));
if (strcmp(p, "0") == 0) {
printf("\nconnection lost\n");
term_clear();
printf("\nconnection lost");
break;
}
}
}
fputs("\n", stdout);
printf("\nexit %s\n", prompt);
term_save_hist(1); /* save history without last line */
return 0;
OnError:
if (savehist) term_save_hist(0); /* save history with last line */
ErrShow("end");
return 0;
}

View File

@ -21,6 +21,7 @@
#endif
#define TABLE_FILE "tecs.cfg"
#define DEV_LIST "dev.list"
#define LSC_CODES "lsc.codes"
#define LOGLIFETIME 24*3600
@ -168,8 +169,7 @@ static int
swRangeOn=0, /* switch heater range on when controller switched it off */
initMaxPower=0, /* set MaxPower for the first time */
lockAlarm,
cntError,
tableTime; /* last time when table was read */
cntError;
int tim, rdTim; /* actual time, read Time */
@ -536,14 +536,12 @@ int InstalCurve(SensorT *sensor, char *devArg) {
return -1;
}
int ReadTable(void) {
int ReadTable(void) { /* obsolete */
char nbuf[256];
if (table!=NULL && tim>tableTime+60) { FREE(table); table=NULL; }; /* clear old table */
if (table!=NULL) return 0;
if (table!=NULL) { FREE(table); table=NULL; };
str_copy(nbuf, binDir);
str_append(nbuf, TABLE_FILE);
ERR_P(table=str_read_file(nbuf));
tableTime=tim;
return 1;
OnError: return -1;
}
@ -574,11 +572,13 @@ int PrepInput(char *label) {
} else {
str_copy(nam, label);
}
again:
str_copy(buf, binDir);
str_append(buf, nam);
str_append(buf, ".cfg");
cfg=str_read_file(buf);
if (cfg==NULL) { /* will be obsolete */
logfileOut(LOG_MAIN, "%s not found, try tecs.cfg\n", buf);
ERR_I(ReadTable());
t=strstr(table, label);
if (t==NULL) ERR_MSG("device not found");
@ -586,6 +586,14 @@ int PrepInput(char *label) {
if (e==NULL || e>strchr(t,'\n')) ERR_MSG("missing ' or device name in table file");
t=e+1;
}
if (cfg && *cfg=='@') { /* alias */
t=strchr(cfg,'\n');
if (t) *t='\0';
str_copy(nam, cfg+1);
str_copy(plug->device, nam);
FREE(cfg);
goto again;
}
if (plug==&plug0) {
InitSensor(&sensA);
InitSensor(&sensB);
@ -694,8 +702,15 @@ int PrepInput(char *label) {
str_copy(plug->device, nam);
ConcatDevice();
}
if (cfg) {
FREE(cfg);
}
return 0;
OnError: return -1;
OnError:
if (cfg) {
FREE(cfg);
}
return -1;
}
int LoadCache(void) {
@ -1708,12 +1723,17 @@ int ConfigByCode(int plugNr) {
}
p=fgets(buf, sizeof(buf), fil);
}
fclose(fil);
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for %s (code %d)\n", plugNr, nam, plug->code);
str_copy(buf, "'");
str_append(buf, nam);
str_append(buf, "'");
ERR_I(PrepInput(buf));
fclose(fil);
if (plug->code != c1 && plug->code != c2) {
logfileOut(LOG_MAIN+LOG_STAT ,"unknown code %d on plug%d\n", plug->code, plugNr);
return 0;
} else {
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for %s (code %d)\n", plugNr, nam, plug->code);
str_copy(buf, "'");
str_append(buf, nam);
str_append(buf, "'");
ERR_I(PrepInput(buf));
}
}
settingsFlag=1;
return 0;
@ -2606,39 +2626,14 @@ EndStatus:
}
int DevHelpHdl(int mode, void *base, int fd) {
char *t, *n, *d, *en, *ed;
char line[80], nbuf[256];
int l, iret;
static int doit=1;
char nbuf[256];
char *list;
ERR_I(iret=ReadTable());
if (iret) doit=1;
if (doit) {
doit=0;
t=table;
str_copy(devHelp,"\n");
while (t!=NULL) {
t++;
n=strchr(t, '\'');
d=strstr(t, "dev=\"");
t=strchr(t, '\n');
if (n!=NULL && d!=NULL && n < d && d < t) {
en=strchr(n+1, '\'');
ed=strchr(d+5, '"');
if (en != NULL && en<d && ed != NULL && ed<t) {
l=en-n;
if (l>12) l=12;
str_ncpy(line, n+1, l);
str_npad(line, line, 12);
l=ed-d;
if (l>77) l=77;
str_ncpy(line+12, d+5, l);
str_append(line, "\n");
str_append(devHelp, line);
}
}
}
}
str_copy(nbuf, binDir);
str_append(nbuf, DEV_LIST);
ERR_P(list=str_read_file(nbuf));
str_copy(devHelp, list);
FREE(list);
return 0;
OnError: return -1;
}
@ -2901,7 +2896,7 @@ int main(int argc, char *argv[]) {
CocDefInt(relay, RW); CocHdl(RelayHdl);
CocDefInt(manual, RW); CocHdl(ManualHdl);
CocDefInt(htrst, RD);
CocDefInt(loop, RD);
CocDefInt(loop, RW);
CocDefInt(rdTim, RD);
CocDefInt(tim0, RD);
CocDefInt(ibuf, RD);

View File

@ -73,7 +73,8 @@
l=0
1 if (oneCommand) goto 99
if (nfiles .gt. 0) then
read(luns(idx), '(q,a)', err=22,end=22) l, line
read(luns(idx), '(a)', err=22,end=22) line
call str_trim(line, line, l)
print '(x,2a)', prompt(1:promptlen),line(1:max(1,l))
else
call sys_rd_line(line, l, prompt(1:promptlen))

View File

@ -34,6 +34,7 @@
logical yzoom
integer winconf(nwin) ! number of windows below actual
integer showsets
integer nextfocus
real winh
integer nticks
character key*1
@ -128,6 +129,7 @@
allpars=allpars(1:l)//' '//parnam(im)
enddo
showsets=1
nextfocus=0
1 continue
@ -135,6 +137,10 @@
if (iret .lt. 0) goto 99
tdif=myc_now()-t
tdif=tdif-mod(tdif+1800*25, 3600)+1800 ! round to next full hour
if (tdif .gt. 7200 .or. tdif .lt. -7200) then ! a hack
t=myc_now()
tdif=0
endif
if (tdif .ne. 0) then
print *,'time difference ',tdif/3600,' h'
endif
@ -258,16 +264,18 @@
endif
enddo
if (j .eq. 0) then
if (.not. yzoom) then
if (nextfocus .ne. 0) then
do is=1,nset
im=imx(is)
if (retLen(is) .gt. 0 .and. unit(im) .eq. 1) focus(im)=.true.
enddo
else if (.not. yzoom) then
y1=ymin(1)
y2=ymax(1)
yzoom=.true.
endif
! do is=1,nset
! im=imx(is)
! if (retLen(is) .gt. 0 .and. unit(im) .eq. 1) focus(im)=.true.
! enddo
endif
nextfocus=0
if (saveit) goto 9
if (mode .eq. live) then
x2=max(tim0,x2)+min(1800., window*0.5)
@ -360,8 +368,8 @@
ey=(ymax(rl)-ymin(rl))
fy=abs(ymax(rl))
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.01)
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
ymax(rl)=ymax(rl)+max(fy*0.02,ey*0.01)
ymin(rl)=ymin(rl)-max(fy*0.02,ey*0.01)
if (mode .eq. live) then
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
@ -628,7 +636,7 @@
elseif (key .eq. 'X') then
window=0
mode=0
yzoom=.true.
yzoom=.false.
elseif (key .eq. '+' .or. key .eq. ',') then
window=max(winmin,window/2)
if (ex .eq. undef) then
@ -759,6 +767,7 @@
goto 9
elseif (key .eq. 'A') then
showsets=2
yzoom=.false.
elseif (key .eq. 'C') then ! clear set
if (ex .lt. x1) then
if (ey .ge. ymin(1) .and.
@ -806,17 +815,28 @@
endif
enddo
if (n .gt. 1) then
if (j .gt. 4) then ! was "all", set to "default"
if (j .gt. 3) then ! was "all", set to "default"
focus(1)=.true.
focus(2)=.true.
focus(3)=.true.
else ! was "default" select 1
focus(1)=.true.
endif
else if (j .lt. nset) then ! select next
im=imx(j)
goto 89
endif
nextfocus=1
do is=1,nset
im=imx(is)
if (im .gt. j) then ! select next
focus(im)=.true.
goto 89
endif
enddo
! select all
do is=1,nset
im=imx(is)
focus(im)=.true.
endif ! else select none -> will be all
enddo
89 yzoom=.false.
elseif (mode .eq. live) then
goto 7

View File

@ -201,8 +201,7 @@ char *term_fgets(char *buf, int size, FILE *fil) {
return ret;
}
void term_save_hist(int
trimlast) {
void term_save_hist(int trimlast) {
FILE *fil;
int i,n;
if (filehead[0]=='\0') return;
@ -319,6 +318,11 @@ int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
}
hist_pos=hist_end;
term_save_hist(0);
printf("\r\033[K\n");
for (i = strlen(prompt) - 1; i > 0; i--) {
printf("-");
}
printf(" %s", buf);
return(STDIN_FILENO);
/* normal EXIT */