Files
sics/tecs/tecs.c
2000-04-07 07:09:42 +00:00

971 lines
26 KiB
C

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/timeb.h>
#include <string.h>
#include <ctype.h>
#include "err_handling.h"
#include "coc_server.h"
#include "coc_logfile.h"
#include "str_util.h"
#include "tecs_lsc.h"
#include "tecs_dlog.h"
#define TABLE_FILE "lsci.tab"
#define NO_CODE 999
#define Progress(I) if (configuring) { configuring+=I; }
static SerChannel *ser=NULL;
static char *serverId=NULL;
static char *binDir=NULL;
static char *logDir=NULL;
static DlogSet dset;
typedef struct {
float temp, t1, t2; /* calc, high, low temperature */
int dirty; /* input config to be reloaded */
int try; /* trial count */
int manual; /* manual device */
int code, code1; /* device code, buffer for device code */
int nSens; /* number of sensors */
int codChanged; /* code has changed */
int codDefined; /* code is not yet confirmed */
char ch1[2], ch2[2]; /* channels for high/low T */
char device[16]; /* device name */
char tname[16];
} Testpoint;
Testpoint /* C standard guarantees initialization to zero */
cryo, /* data for main sensors (on heat exchanger, or the only sensors) */
samp, /* data for extra sensors of sample stick */
*testpoints[2]={&cryo, &samp},
*testpoint=&cryo;
static float
tempC, /* set T */
tempH, /* set T on heater */
htr, /* heat power */
tLimit, power, /* heater parameters */
tLow=0, tHigh=0, /* lower limit of high-T sensor, upper limit of low-T sensor */
tShift=0, /* setpoint shift */
tInt=0; /* integral time (sec.) for setpoint shift */
static int
logPeriod=10, /* data logging period (sec.) */
period=5000, /* default read interval (msec.) */
logTime, /* next logging time */
setFlag, /* temperature to be set */
remoteFlag, /* to be set to remote mode */
saveTime, /* time for a CRVSAV command */
noResp=1, /* no response */
quit, /* quit server */
controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */
mode, /* 0: local, 2: remote */
maxfld, /* last used display field */
busy, /* busy after CRVSAV */
deviceFlag, /* device given via net */
num, /* curve number */
fld, /* field number */
key, /* key status */
serialNo,
configuring=1,
resist, /* heater resistance */
readTemp, /* client requested readTemp */
cod1, cod2, out1, out2, /* codes read from digital input/output */
iRange, iAmp, /* max. range and max. current code */
per; /* effective period */
static time_t
auto_remote_time, /* time for automatic reload */
tim, /* actual time */
tableTime; /* last time when table was read */
static int decod[8]={21,20,17,16,5,4,1,0}; /* for code conversion */
static char
status[132], /* status buffer */
device[32], /* concatenated device names */
buf1[256], buf2[256], buf3[256], buf4[256], /* buffers for temporary use */
head[64], /* curve header */
intype[64], /* input configuration */
chan[2]; /* actual channel */
static char
*table=NULL, /* environment devices table */
*cache=NULL; /* curve list cache */
struct timeb tim0;
int logMask;
void idleHdl(int tmo, int fd) {
int iRet;
iRet=CocHandleRequests(tmo, fd);
if (iRet<0) logfileShowErr("CocHandleRequests");
}
void concatDevice() {
str_copy(device, cryo.device);
if (0!=strcmp(cryo.device, samp.device) && (samp.device[0]!='\0' || samp.manual)) {
str_append(device, "/");
str_append(device, samp.device);
}
}
int instCurve(char *nam, char *channel) {
/*
install sensor nam on channel
*/
char buf[256], chead[64], nbuf[256], lbuf[16];
char *crv, *entry, *points, *start,
*s, /* start of found entry */
*e, /* cache part after found entry */
*res, *t;
int i, n;
char used[60];
FILE *fil;
int retstat;
str_copy(chan, channel);
logfileOut(LOG_MAIN, "install curve %s\n", nam);
fil=NULL;
crv=NULL;
/* read curve file */
str_copy(nbuf, binDir);
str_append(nbuf, nam);
retstat=-2; /* an error would be severe */
ERR_P(crv=str_read_file(nbuf));
t=str_split(chead, crv, '\n');
if (t==NULL) {
points=NULL;
} else {
points=str_split(intype, t, '\n');
}
if (points==NULL) ERR_MSG("illegal curve file");
if (points[0]=='$') { /* standard curve */
points++; num=atoi(points);
if (num>20) ERR_MSG("illegal standard curve number");
retstat=-1; /* an error could be fixed */
ERR_P(LscCmd(ser, "CRVHDR?[num]>head"));
} else {
strcpy(buf, ":");
str_append(buf, nam);
str_append(buf, " ");
str_upcase(buf, buf);
if (cache==NULL) { cache=malloc(1); *cache='\0'; } /* create empty cache if undefined */
start=strchr(cache, '\n'); /* skip device names */
if (start==NULL) { start=cache; } else { start++; }
entry=strstr(start, buf);
if (entry==NULL) { /* sensor not found in cache */
entry=start;
for (i=60;i>20;i--) used[i]=0;
n=40; num=0;
while (entry!=NULL && n>0) {
i=0;
sscanf(entry, "%d", &i);
if (i>20 && i<=60) { num=i; s=entry; used[i]=1; n--; }
entry=strchr(entry, '\n');
if (entry !=NULL) entry++;
}
if (n>0) {
for (num=60;num>20;num--) { if (used[num]==0) break; }
s=NULL;
e=NULL;
} else {
e=strchr(s, '\n');
if (e!=NULL) { *e='\0'; e++; }
if (s>start) { s--; *s='\0'; }
}
head[0]='\0';
} else {
s=entry; entry++;
while (s>start && *s!='\n') s--;
if (s>start) { *s='\0'; s++; }
num=0;
sscanf(s, "%d", &num);
if (num<21 || num>60) ERR_MSG("illegal curve number");
retstat=-1; /* an error could be fixed */
ERR_P(LscCmd(ser, "CRVHDR?[num]>head"));
e=strchr(entry, '\n');
if (e!=NULL) { *e='\0'; e++; }
}
}
fld=chan[0]-'A'+1;
if (fld>maxfld) maxfld=fld;
if (head[0]!='\0' && LscEqPar(head, chead)) { /* header matches: select sensor type and curve */
retstat=-1; /* an error could be fixed */
ERR_P(LscCmd(ser, "INTYPE [chan]:[intype];INCRV [chan]:[num];DISPFLD [fld],[chan],1;DISPLAY:[maxfld]"));
logfileOut(LOG_MAIN, "curve %d on channel %s selected\n", num, chan);
} else { /* header does not match -> download */
retstat=-2; /* an error would be severe */
if (num<=20) ERR_MSG("standard curve does not match");
retstat=-1; /* an error could be fixed */
if (busy) ERR_MSG("busy");
logfileOut(LOG_MAIN, "download curve %d\n", num);
/* select sensor type first to display sensor units */
ERR_P(LscCmd(ser, "INTYPE [chan]:[intype];DISPFLD [fld],[chan],3;DISPLAY:[maxfld]"));
Progress(1);
n=3;
do {
ERR_P(LscCmd(ser, "CRVDEL [num];CRVHDR?[num]>buf1,"));
buf1[4]='\0';
i=strcmp(buf1, "User");
n--;
} while (i!=0 && n!=0);
if (i!=0) ERR_MSG("can not delete curve");
sprintf(lbuf, "CRVPT %d", num);
i=0;
do { /* download curve */
t=str_split(nbuf, points, '\n');
if (nbuf[0]!='\0') {
ERR_I(str_substitute(buf, nbuf, "#0", lbuf));
ERR_P(LscCmd(ser, buf));
i++;
if (i%10==0) sprintf(status, "downloading curve at line %d", i);
Progress(1);
}
points=t;
} while (t!=NULL);
/* write header, select curve */
str_upcase(head, chead);
ERR_P(LscCmd(ser, "CRVHDR [num]:[head];INCRV [chan]:[num];DISPFLD [fld],[chan],1"));
Progress(1);
logfileOut(LOG_MAIN, "curve selected on channel %s\n", chan);
saveTime=tim+30;
}
free(crv); crv=NULL;
if (num<=20) return(0); /* standard curve, do not touch cache */
/* rewrite cache with actual entry at beginning */
retstat=-2; /* errors in following section are severe */
sprintf(lbuf, "lsc.%d", serialNo);
str_copy(nbuf, logDir);
str_append(nbuf, lbuf);
fil=fopen(nbuf, "r+");
if (fil==NULL) ERR_SP(fil=fopen(nbuf, "w"));
if (cryo.manual) ERR_SI(fputs(cryo.device, fil));
ERR_SI(fputs("/", fil));
if (samp.manual) ERR_SI(fputs(samp.device, fil));
ERR_SI(fputs("\n", fil));
sprintf(buf, "%d:%s", num, head);
ERR_SI(fputs(buf, fil)); /* write actual entry */
if (start!=s) { /* write content before replaced entry */
ERR_SI(fputs("\n", fil));
ERR_SI(fputs(start, fil));
}
if (e!=NULL) { /* write content after replaced entry */
ERR_SI(fputs("\n", fil));
ERR_SI(fputs(e, fil));
}
ERR_SI(fclose(fil));
fil=NULL;
free(cache);
/* re-read it */
ERR_P(cache=str_read_file(nbuf));
return(0);
OnError:
if (crv!=NULL) free(crv);
if (fil!=NULL) fclose(fil);
return(retstat);
}
int configInput() {
char *t;
char buf[80], nam[16], nbuf[256];
int i, n, nn;
int retstat;
char *ext;
retstat=-2; /* errors in following section are severe */
if (testpoint->manual) {
sprintf(buf, "'%s'", testpoint->device);
} else {
sprintf(buf, "%+d ", testpoint->code);
if (testpoint->code==0) return(0);
}
if (table!=NULL && tim>tableTime+60) { free(table); table=NULL; }; /* clear old table */
if (table==NULL) { /* read table */
str_copy(nbuf, binDir);
str_append(nbuf, TABLE_FILE);
ERR_P(table=str_read_file(nbuf));
tableTime=tim;
str_replace_char(table, 9, ' '); /* replace TAB (9) by space in order to find codes terminated by tab */
}
t=strstr(table, buf);
if (t==NULL) ERR_MSG("device not found");
i=sscanf(t, "%79[^\n!]", buf); /* read line */
t=strchr(buf, '\'');
if (t==NULL) ERR_MSG("missing ' in table file");
t++;
n=1;
if (testpoint==&samp) {
samp.nSens=0;
i=sscanf(t, "%12s%d%d", nam, &nn, &n);
if (i<1) ERR_MSG("missing sensor name");
ext=".s";
} else {
cryo.nSens=0;
tLow=0; tHigh=0;
controlMode=0;
i=sscanf(t, "%12s%d%d%d%f%d%f%f%f", nam, &n, &nn, &controlMode, &tLimit, &resist, &power, &tLow, &tHigh);
if (i<7) ERR_MSG("missing some sensor parameters");
ext=".x";
}
if (n<0 || n>2) ERR_MSG("illegal value for nsensor");
if (n==0) return(0);
nam[strlen(nam)-1]='\0'; /* strip off quote */
if (!testpoint->manual) { /* set device name */
str_copy(testpoint->device, nam);
concatDevice();
}
str_append(nam, ext);
ERR_I(retstat=instCurve(nam, testpoint->ch1));
if (n==2) {
str_append(nam, "l");
ERR_I(retstat=instCurve(nam, testpoint->ch2));
}
testpoint->nSens=n;
return(0);
OnError: return(retstat);
}
int loadCache() {
int i, j, k;
char *res;
char buf[256], nbuf[256], lbuf[16];
char *bufi[4];
FILE *fil;
fil=NULL;
sprintf(lbuf, "lsc.%d", serialNo);
str_copy(nbuf, logDir);
str_append(nbuf, lbuf);
ERR_SP(fil=fopen(nbuf, "w"));
if (cryo.manual) ERR_SI(fputs(cryo.device, fil));
ERR_SI(fputs("/", fil));
if (samp.manual) ERR_SI(fputs(samp.device, fil));
ERR_SI(fputs("\n", fil));
bufi[0]=buf1;
bufi[1]=buf2;
bufi[2]=buf3;
bufi[3]=buf4;
for (i=60; i>21; i-=4) {
sprintf(buf, "CRVHDR?%d>buf1;CRVHDR?%d>buf2;CRVHDR?%d>buf3;CRVHDR?%d>buf4", i, i-1, i-2, i-3);
Progress(1);
ERR_P(LscCmd(ser, buf));
k=0;
for (j=i; j>i-4; j--) {
res=bufi[k]; k++;
if (res[1]=='s') { i=0; break;} /* s of "User", must be empty slot, lowercase letters are not programmable */
sprintf(buf, "%d:", j);
ERR_SI(fputs(buf, fil));
ERR_SI(fputs(res, fil));
ERR_SI(fputs("\n", fil));
}
}
ERR_SI(fclose(fil));
/* re-read cache */
ERR_P(cache=str_read_file(nbuf));
return(0);
OnError:
if (fil!=NULL) fclose(fil);
return(-1);
}
float WeightedAverage(int n, float t1, float t2) {
float p,q;
if (n==0) {
return(0.0);
} else if (n<2) {
return(t1);
} else {
if (t2<tLow) {
return(t2);
} else if (t1<tHigh) {
p=tHigh-t1;
q=t2-tLow;
return((t1*p*p+t2*q*q)/(p*p+q*q));
} else {
return(t1);
}
}
}
int SetTemp(int switchOn) {
char *ch;
if (tempC==0) {
ERR_P(LscCmd(ser, "RANGE:0;SETP 1:0"));
return(0);
}
ch=cryo.ch1;
if (cryo.nSens>1 && tempC<(tLow+tHigh)/2) ch=cryo.ch2;
if (samp.nSens>0) {
if (controlMode==1) { /* control directly on sample sensor */
tShift=0;
ch=samp.ch1;
if (cryo.nSens>1 && tempC<(tLow+tHigh)/2) ch=samp.ch2;
} else if (controlMode!=2) {
tShift=0;
}
} else {
tShift=0;
}
str_copy(chan, ch);
tempH=tempC+tShift;
if (switchOn) {
ERR_P(LscCmd(ser, "CSET 1:[chan],1,1,0;RANGE:[iRange];SETP 1:[tempH]"));
} else {
ERR_P(LscCmd(ser, "CSET 1:[chan],1;SETP 1:[tempH]"));
}
return(0);
OnError: return(-1);
}
int ReadTemp() {
char buf[256];
int i;
readTemp=0;
buf[0]='\0';
if (cryo.nSens>0) {
str_append(buf, "KRDG?[cryo.ch1]>cryo.t1;");
if (cryo.nSens>1) {
str_append(buf, "KRDG?[cryo.ch2]>cryo.t2;");
} else {
cryo.t2=0;
}
} else {
cryo.t1=0;
cryo.t2=0;
}
if (samp.nSens>0) {
str_append(buf, "KRDG?[samp.ch1]>samp.t1;");
if (samp.nSens>1) {
str_append(buf, "KRDG?[samp.ch2]>samp.t2;");
} else {
samp.t2=0;
}
} else {
samp.t1=0;
samp.t2=0;
}
i=strlen(buf);
if (i>0) {
buf[i-1]='\0'; /* strip off ';' */
ERR_P(LscCmd(ser, buf));
}
cryo.temp=WeightedAverage(cryo.nSens, cryo.t1, cryo.t2);
samp.temp=WeightedAverage(samp.nSens, samp.t1, samp.t2);
if (samp.temp==0.0) samp.temp=cryo.temp;
if (!deviceFlag
&& !samp.dirty && samp.codDefined && !samp.codChanged
&& !cryo.dirty && cryo.codDefined && !cryo.codChanged) {
configuring=0;
} else if (configuring==0) {
str_copy(status, "configuring");
configuring=1;
}
return(0);
OnError: return(-1);
}
int PeriodicTask() {
char buf[256], lbuf[16];
char *res;
int i, k;
float t2[2], p, d;
ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;HTR?>htr;BUSY?>busy"));
if (cryo.codDefined) {
per=period;
} else {
per=1; /* advance fast when initializing */
}
if (noResp) { /* check serial number */
k=serialNo;
ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo,"));
if (0!=strcmp(buf1, "LSCI") || 0!=strcmp(buf2, "MODEL340") || serialNo==0) return(0);
if (k!=serialNo) {
if (!configuring) {
str_copy(status, "controller connected");
configuring=1;
}
if (cryo.manual || cryo.code!=0) { cryo.dirty=1; }
if (samp.manual || samp.code!=0) { samp.dirty=1; }
ERR_P(LscCmd(ser, "RANGE:0")); /* switch off heater */
/* reload curve cache: */
if (cache!=NULL) free(cache);
sprintf(lbuf, "lsc.%d", serialNo);
str_copy(buf, logDir);
str_append(buf, lbuf);
cache=str_read_file(buf);
if (cache==NULL && 0==strcmp(ErrMessage, "file not found")) ERR_I(loadCache());
cryo.device[0]='\0';
samp.device[0]='\0';
sscanf(cache, "%15[^/!]%*c%15[^\n!]", cryo.device, samp.device); /* read device names separated by '/' */
if (cryo.device[0]!='\0') cryo.manual=1;
if (samp.device[0]!='\0') samp.manual=1;
concatDevice();
}
noResp=0;
}
ERR_I(ReadTemp());
if (cryo.dirty==0 && samp.dirty==0 && noResp==0 && tim>logTime) {
t2[0]=cryo.temp;
t2[1]=samp.temp;
DlogPut(&dset, tim, 2, t2); DlogUpd(&dset);
logTime=(tim/logPeriod+1)*logPeriod;
}
if (samp.nSens>0 && cryo.nSens>0 && controlMode==2 && tempC!=0) {
d=tempH-cryo.temp; d=exp(-d*d); /* if d is small, we are far from setpoint */
if (tInt<60000/period) tInt+=d; /* increase integral time until 60 sec. */
if (tInt>d) {
p=d/tInt;
} else {
p=1.0;
}
tShift=tShift*(1.0-p)+p*(cryo.temp-samp.temp);
ERR_I(SetTemp(0));
}
ERR_P(LscCmd(ser, "KEYST?>key;DIOST?>cod2,out2;DOUT 3,30"));
if (busy==0) {
if (out1!=30) {
ERR_P(LscCmd(ser, "DOUT:3,30"));
ERR_P(LscCmd(ser, "DIOST?>cod1,out1"));
}
if (out2!=29) {
ERR_P(LscCmd(ser, "DOUT:3,29"));
ERR_P(LscCmd(ser, "DIOST?>cod2,out2;DOUT 3,30"));
}
if (out1==30 && out2==29) {
/* code conversion */
cryo.code1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */
samp.code1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]);
for (i=0; i<2; i++) {
testpoint=testpoints[i];
if (testpoint->code1!=testpoint->code) {
testpoint->code=testpoint->code1;
testpoint->codChanged=1;
} else {
if (testpoint->codChanged) {
testpoint->codChanged=0;
if (testpoint->code1==0) {
logfileOut(LOG_MAIN, "%s unplugged\n", testpoint->tname);
} else {
logfileOut(LOG_MAIN, "plugged %d on %s\n", testpoint->code1, testpoint->tname);
}
if (testpoint->codDefined) {
testpoint->manual=0;
}
testpoint->dirty=1;
if (!configuring) configuring=1;
}
testpoint->codDefined=1;
}
}
}
}
if (key!=0) {
auto_remote_time=tim+600;
if (!(cryo.dirty || samp.dirty)) {
logfileOut(LOG_MAIN ,"user touched keys\n");
}
if (cryo.manual || cryo.code!=0) cryo.dirty=1;
if (samp.manual || samp.code!=0) samp.dirty=1;
mode=0;
ERR_P(LscCmd(ser, "MODE?>mode"));
if (mode==2) auto_remote_time=tim; /* user switched to remote mode */
}
return(0);
OnError: return(-1);
}
int inputSettings(Testpoint *this) {
testpoint=this;
if (testpoint->dirty && samp.codDefined) {
if (busy==0 || cryo.dirty>=0 && testpoint->dirty>=0) { /* do not enter when busy and cryo.dirty/P indicates error on last time */
if (testpoint->manual) {
logfileOut(LOG_MAIN ,"configure %s inputs for %s\n", testpoint->tname, testpoint->device);
} else {
if (testpoint->code==0) {
logfileOut(LOG_MAIN ,"reset %s inputs\n", testpoint->tname);
} else {
logfileOut(LOG_MAIN ,"configure %s inputs for code %+d\n", testpoint->tname, testpoint->code);
}
}
if (testpoint->dirty>0) testpoint->try=0;
testpoint->nSens=0;
if (!testpoint->manual) { testpoint->device[0]='\0'; concatDevice(); }
testpoint->dirty=configInput();
if (testpoint->dirty<0) {
testpoint->try++;
if (testpoint->dirty!=-1 || testpoint->try>3) {
logfileShowErr("fatal error");
testpoint->dirty=0; testpoint->device[0]='\0'; concatDevice();
} else {
logfileShowErr("try again");
}
} else {
ERR_P(LscCmd(ser, "ALARM [testpoint.ch1]:[testpoint.nSens],1,[tLimit],0,0,1;ALARM [testpoint.ch2]:0;RELAY 1:1;BEEP:0"));
}
}
}
return(0);
OnError: return(-1);
}
int Settings() {
int i, j, k;
float pa, pr, pw, dif;
if (cryo.dirty && cryo.codDefined || samp.dirty && samp.codDefined) {
for (i=0; i<2; i++) {
testpoint=testpoints[i];
if (testpoint->dirty) {
ERR_P(LscCmd(ser, "DISPFLD 2,[testpoint.ch1],1;DISPFLD 4,[testpoint.ch2],1"));
}
}
inputSettings(&cryo);
inputSettings(&samp);
if (cryo.nSens>0) {
/* control settings */
ERR_P(LscCmd(ser, "CDISP 1:1,[resist],1;MOUT 1:0;CMODE 1:1"));
iAmp=1; iRange=0;
if (power>0) {
pa=resist*4; /* max. power */
pw=0; dif=1.0e6;
for (i=4; i>0; i--) {
pr=pa;
for (j=5; j>0; j--) {
if (pr>power) {
if (pr/power<dif) { dif=pr/power; pw=pr; iAmp=i; iRange=j; }
} else {
if (power/pr<dif) { dif=power/pr; pw=pr; iAmp=i; iRange=j; }
}
pr=pr/10;
}
pa=pa/4;
}
}
power=pw;
logfileOut(LOG_INFO, "power %f\n", power, iAmp, iRange);
ERR_P(LscCmd(ser, "CLIMIT 1:[tLimit],0,0,[iAmp],[iRange]"));
tempC=0.001; tShift=0;
ERR_I(SetTemp(1));
tempC=0;
}
if (samp.nSens>=cryo.nSens) {
maxfld=2*samp.nSens;
} else {
maxfld=2*cryo.nSens-1;
}
if (maxfld>0) {
ERR_P(LscCmd(ser, "MODE:2;DISPLAY:[maxfld]"));
} else {
maxfld=1;
ERR_P(LscCmd(ser, "MODE:2;DISPLAY:1;DISPFLD 1,A,3"));
}
mode=2;
if (saveTime!=0 && tim>saveTime) {
ERR_P(LscCmd(ser, "CRVSAV;BUSY?>busy"));
while (!busy) {
idleHdl(200, 0); /* wait 200 ms */
ERR_P(LscCmd(ser, "BUSY?>busy"));
}
saveTime=0;
}
}
return(0);
OnError: return(-1);
}
int ExecuteRequest() {
char *t, *res;
struct CocClient *client;
if (readTemp) ReadTemp();
if (tim>auto_remote_time || setFlag) ERR_I(Settings());
if (setFlag) {
if (cryo.nSens>0) {
tInt=0; /* reset integral time */
ERR_I(SetTemp(1));
}
setFlag=0;
}
client=CocGetNextCmd();
if (client!=NULL) {
if (NULL!=strchr(client->cmd, '>') || NULL!=strchr(client->cmd, '[')) ERR_MSG("no variables allowed");
res=LscCmd(ser, client->cmd);
if (res==NULL && ErrMessage!=NULL) {
str_copy(client->res, ErrMessage);
} else {
str_copy(client->res, res);
}
client->cmd[0]='\0';
}
if (deviceFlag) {
if (!configuring) {
str_copy(status, "configuring");
configuring=1;
}
t=strchr(device, '/');
if (t==NULL) {
if (0==strcmp(device, "0")) {
cryo.manual=0; cryo.dirty=1;
samp.manual=0; samp.dirty=1;
} else {
str_copy(cryo.device, device);
str_copy(samp.device, device);
cryo.manual=1; cryo.dirty=1;
samp.manual=1; samp.dirty=1;
}
} else {
if (t!=device) {
*t='\0';
str_copy(cryo.device, device);
*t='/';
cryo.manual=1; cryo.dirty=1;
}
t++;
if (*t!='\0') {
str_copy(samp.device, t);
samp.manual=1; samp.dirty=1;
}
}
concatDevice();
deviceFlag=0;
}
return(0);
OnError: return(-1);
}
int mainBody(void)
{
int i, iret, tdif;
struct timeb tim1;
ERR_I(PeriodicTask());
if (tim>=auto_remote_time) ERR_I(Settings());
logfileWrite(logMask);
while (!quit) {
ftime(&tim1);
tdif=per-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
if (tdif<0) { tim=tim1.time; break; } /* timeout */
ERR_I(iret=CocHandleRequests(tdif, 0));
if (iret==0) { time(&tim); break; } /* timeout */
tim=tim1.time;
ERR_I(ExecuteRequest());
logfileWrite(logMask);
}
ftime(&tim1);
tdif=((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm)/period;
i=period*tdif+tim0.millitm;
tim0.time+=i / 1000;
tim0.millitm=i % 1000;
if (tdif>1) {
logfileOut(LOG_INFO ,"%d cycles lost\n", tdif-1);
}
return(0);
OnError:
if (0==strcmp(ErrMessage, "timeout")) {
if (!noResp) logfileOut(LOG_MAIN ,"no response\n");
per=period+10000; /* long period if no response */
noResp=1;
return(0);
}
return(-1);
}
int main(int argc, char *argv[])
{ int logIt=0;
int i, iret, use_stdout=0;
char *host;
char buf[256], opt;
int port, msecTmo;
str_copy(cryo.tname,"main");
str_copy(cryo.ch1,"A");
str_copy(cryo.ch2,"B");
str_copy(samp.tname,"sample stick");
str_copy(samp.ch1,"C");
str_copy(samp.ch2,"D");
cryo.codChanged=1;
samp.codChanged=1;
logMask=LOG_MAIN+LOG_INFO;
binDir="bin/";
logDir="log/";
serverId="tecs";
host="lnsp26";
port=0;
msecTmo=0;
logfileOut(LOG_INFO ,"%s ", argv[0]);
for (i=1;i<argc;i++) {
if (argv[i]!=NULL) {
if (argv[i][0]=='-') {
opt=tolower(argv[i][1]);
} else {
opt=' ';
}
if ('l'==opt) {
logIt=1;
logMask=LOG_ALL;
opt=' ';
} else if ('s'==opt) {
use_stdout=1;
opt=' ';
} else if ('n'==opt) {
i++;
serverId=argv[i];
} else if ('b'==opt) {
i++;
binDir=argv[i];
} else if ('d'==opt) {
i++;
logDir=argv[i];
} else if ('t'==opt) {
i++;
msecTmo=atoi(argv[i]);
} else if ('h'==opt) {
i++;
host=argv[i];
} else if ('p'==opt) {
i++;
port=atoi(argv[i]);
} else {
logfileOut(LOG_INFO ,"?");
}
if (opt!=' ') logfileOut(LOG_INFO ,"-%c ", opt);
logfileOut(LOG_INFO ,"%s ", argv[i]);
}
}
if (port==0) port=9753;
if (msecTmo==0) msecTmo=1000;
str_copy(buf, logDir);
str_append(buf, serverId);
str_copy(status, "starting up");
logfileStatusBuf(status);
logfileInit(buf, logIt, use_stdout, logIt);
logfileOut(LOG_INFO ,"\n");
logfileWrite(logMask);
ERR_I(CocInitServer(1024, port));
CocDefStruct(cryo, Testpoint);
CocDefStruct(samp, Testpoint);
CocDefPtr(testpoint, Testpoint);
CocFltFld(Testpoint, temp, CocRD);
CocFltFld(Testpoint, t1, CocRD);
CocFltFld(Testpoint, t2, CocRD);
CocStrFld(Testpoint, ch1, CocRD);
CocStrFld(Testpoint, ch2, CocRD);
CocDefFlt(htr, CocRD);
CocDefFlt(tempC, setFlag);
CocDefFlt(tempH, CocRD);
CocDefFlt(tLimit, CocRD);
CocAlias(tempX,cryo.temp);
CocAlias(tempP,samp.temp);
CocDefStr(device, deviceFlag);
CocDefStr(buf1, CocRD);
CocDefStr(buf2, CocRD);
CocDefStr(buf3, CocRD);
CocDefStr(buf4, CocRD);
CocDefStr(head, CocRD);
CocDefStr(chan, CocRD);
CocDefStr(intype, CocRD);
CocDefStr(status, CocRD);
CocDefInt(cod1, CocRD);
CocDefInt(cod2, CocRD);
CocDefInt(out1, CocRD);
CocDefInt(out2, CocRD);
CocDefInt(num, CocRD);
CocDefInt(fld, CocRD);
CocDefInt(key, CocRD);
CocDefInt(maxfld, CocRD);
CocDefInt(resist, CocRD);
CocDefInt(iAmp, CocRD);
CocDefInt(iRange, CocRD);
CocDefInt(mode, CocRD);
CocDefInt(readTemp, CocWR);
CocDefInt(controlMode, CocWR);
CocDefInt(busy, CocRD);
CocDefInt(serialNo, CocRD);
CocDefInt(configuring, CocRD);
CocDefInt(quit, CocWR);
ERR_P(ser=SerOpen(host, msecTmo, idleHdl));
ERR_I(iret=CocHandleRequests(100, 0));
ftime(&tim0);
tim=tim0.time;
str_copy(buf, logDir);
str_append(buf, serverId);
str_append(buf, ".dlog");
iret=DlogOpen(&dset, buf, 1);
if (iret<0) {
logfileOut(LOG_INFO, "create data log file: %s\n", buf);
ERR_I(DlogCreate(&dset, buf, tim0.time, 2, 7*24*60*60/logPeriod, logPeriod, 0.0));
} else {
logfileOut(LOG_INFO, "opened data log file: %s\n", buf);
}
logfileWrite(logMask);
per=period;
while (!quit) {
iret=mainBody();
if (iret<0) logfileShowErr("error in TecsServer");
}
ERR_MSG("got quit command");
OnError:
logfileShowErr("exit TecsServer");
DlogClose(&dset);
SerClose(ser);
CocCloseServer();
return(0);
}