- extended evcontroller
- remote objects - new ev drivers for oxford IPS,ITC,ILM and LC M.Z.
This commit is contained in:
137
eve.h
Normal file
137
eve.h
Normal 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
117
fsm.c
Normal 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
66
fsm.h
Normal 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
145
ilmdriv.c
Normal 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;
|
||||
}
|
272
itcdriv.c
Normal file
272
itcdriv.c
Normal 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
184
lcdriv.c
Normal 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
352
logger.c
Normal 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
19
logger.h
Normal 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
|
4
make_gen
4
make_gen
@ -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
128
oicom.c
Normal 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
16
oicom.h
Normal 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
35
psi.c
@ -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
785
remob.c
Normal 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
19
remob.h
Normal 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
|
||||
|
13
tecs/didi
13
tecs/didi
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
20
tecs/six.c
20
tecs/six.c
@ -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;
|
||||
}
|
||||
|
87
tecs/tecs.c
87
tecs/tecs.c
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user