1357 lines
36 KiB
C
1357 lines
36 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 "sys_util.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"
|
|
|
|
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */
|
|
|
|
#define TABLE_FILE "lsci.tab"
|
|
#define Progress(I) if (configuring) { configuring+=I; }
|
|
#define undef -65535.
|
|
|
|
static SerChannel *ser=NULL;
|
|
static char *serverId=NULL;
|
|
static char *binDir=NULL;
|
|
static char *logDir=NULL;
|
|
|
|
typedef struct {
|
|
float t, min, max; /* temperatures */
|
|
int sMin, sMax; /* reading status summary */
|
|
int present; /* sensor is present */
|
|
int readStat; /* reading status */
|
|
char ch[2]; /* channels */
|
|
} SensorT;
|
|
|
|
SensorT
|
|
sens1, sens2, sens3, sens4,
|
|
*sensors[5]={NULL, &sens1, &sens2, &sens3, &sens4 },
|
|
*sensor=&sens1;
|
|
|
|
typedef struct {
|
|
SensorT *sensor1, *sensor2;
|
|
float temp; /* weighted temperature */
|
|
float tMin, tMax; /* minimum and maximum temperatures since ... */
|
|
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 codChanged; /* code has changed */
|
|
int codDefined; /* code is not yet confirmed */
|
|
float scale; /* scale for extreme ranges */
|
|
char device[16]; /* device name */
|
|
char tname[16];
|
|
} Testpoint;
|
|
|
|
Testpoint /* C standard guarantees initialization to zero */
|
|
cryo={&sens1, &sens2 }, /* data for main sensors (on heat exchanger, or the only sensors) */
|
|
samp={&sens3, &sens4 }, /* data for extra sensors of sample stick */
|
|
*tpoints[2]={&cryo, &samp},
|
|
*tpoint=&cryo;
|
|
|
|
static float
|
|
tempC, /* set T (for sample) */
|
|
tempH, /* set T on heat exchanger */
|
|
htr, /* heat power percentage */
|
|
tLimit, power, /* heater parameters */
|
|
tLow=0, tHigh=0, /* lower limit of high-T sensor, upper limit of low-T sensor */
|
|
tShift=0, /* setpoint shift */
|
|
prop, integ, deriv, /* pid */
|
|
maxShift=2, /* maximal shift in when controlMode=2 */
|
|
tInt=0; /* integral time (sec.) for setpoint shift */
|
|
|
|
static int
|
|
logPeriod=0, /* data logging period (sec.) */
|
|
period=5000, /* default read interval (msec.) */
|
|
logTime, /* next logging time */
|
|
setFlag, /* temperature to be set */
|
|
powerFlag, /* power to be set */
|
|
pidFlag, /* pid's to be set */
|
|
saveTime, /* time for a CRVSAV command */
|
|
noResp=2, /* no response */
|
|
quit, /* quit server */
|
|
controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */
|
|
int2=30, /* inegration time for controlMode 2 */
|
|
remoteMode, /* 1: 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,
|
|
stable, /* stable since 2 min. */
|
|
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 */
|
|
htrst, htrst0, /* heater status */
|
|
per; /* effective period */
|
|
|
|
static time_t
|
|
tim, /* actual time */
|
|
mmInt, mmTime, /* interval and time for next min-max logging */
|
|
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[64], /* 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 */
|
|
dlogfile[128];
|
|
|
|
static char
|
|
*table=NULL, /* environment devices table */
|
|
*cache=NULL, /* curve list cache */
|
|
*logfile="<none>";
|
|
|
|
static char
|
|
*heaterStatus[7]={
|
|
"heater o.k.\n",
|
|
"heater supply over V\n",
|
|
"heater supply under V\n",
|
|
"heater output DAC error\n",
|
|
"heater Ilimit DAC error\n",
|
|
"open heater load\n",
|
|
"heater load < 10 Ohm\n",
|
|
};
|
|
|
|
struct timeb tim0;
|
|
int logMask;
|
|
|
|
void idleHdl(int tmo, int fd) {
|
|
int iRet;
|
|
|
|
iRet=CocHandleRequests(tmo, fd);
|
|
if (iRet<0) logfileShowErr("CocHandleRequests");
|
|
}
|
|
|
|
void concatDevice(void) {
|
|
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);
|
|
}
|
|
if (cryo.manual) {
|
|
str_append(device, " (manual");
|
|
} else {
|
|
str_append(device, " (auto");
|
|
}
|
|
if (samp.manual==cryo.manual) {
|
|
str_append(device, ")");
|
|
} else if (samp.manual) {
|
|
str_append(device, "/manual)");
|
|
} else {
|
|
str_append(device, "/auto)");
|
|
}
|
|
}
|
|
|
|
int putPermanentData(FILE *fil) {
|
|
char buf[256];
|
|
char *d1, *d2;
|
|
|
|
if (cryo.manual) {
|
|
d1="*";
|
|
} else {
|
|
d1="";
|
|
}
|
|
if (samp.manual) {
|
|
d2="*";
|
|
} else {
|
|
d2="";
|
|
}
|
|
sprintf(buf, "%s%s/%s%s/%d/%d\n", d1, cryo.device, d2, samp.device, cryo.code, samp.code);
|
|
ERR_SI(fputs(buf, fil));
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int instCurve(char *nam, char *channel, int dispFld) {
|
|
/*
|
|
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, c1, c2;
|
|
char used[60];
|
|
FILE *fil;
|
|
int retstat;
|
|
|
|
fil=NULL;
|
|
crv=NULL;
|
|
e=NULL;
|
|
|
|
str_copy(chan, channel);
|
|
logfileOut(LOG_MAIN, "install curve %s\n", nam);
|
|
|
|
/* 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 (cache==NULL) { ERR_SP(cache=my_malloc(1,"one")); *cache='\0'; } /* create empty cache if undefined */
|
|
|
|
start=strchr(cache, '\n'); /* skip permanent data */
|
|
if (start==NULL) { start=cache; } else { start++; }
|
|
|
|
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);
|
|
|
|
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=dispFld;
|
|
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, "RANGE:0;INTYPE [chan]:[intype];INCRV [chan]:[num]"));
|
|
ERR_P(LscCmd(ser, "MNMX [chan]:1,1;DISPFLD [fld],[chan],1;DISPLAY [maxfld]"));
|
|
logfileOut(LOG_MAIN, "curve %d on channel %s selected\n", num, chan);
|
|
Progress(100);
|
|
|
|
} 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, "RANGE:0;INTYPE [chan]:[intype];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]"));
|
|
ERR_P(LscCmd(ser, "MNMX [chan]:1,1;DISPFLD [fld],[chan],1;DISPLAY [maxfld]"));
|
|
Progress(1);
|
|
logfileOut(LOG_MAIN, "curve selected on channel %s\n", chan);
|
|
saveTime=tim+30;
|
|
}
|
|
my_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"));
|
|
ERR_I(putPermanentData(fil));
|
|
if (num>20) { /* write actual entry */
|
|
sprintf(buf, "%d:%s", num, head);
|
|
ERR_SI(fputs(buf, fil));
|
|
}
|
|
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(fputc('\0', fil));
|
|
ERR_SI(fclose(fil));
|
|
fil=NULL;
|
|
my_free(cache);
|
|
/* re-read it */
|
|
ERR_P(cache=str_read_file(nbuf));
|
|
return(0);
|
|
|
|
OnError:
|
|
if (crv!=NULL) my_free(crv);
|
|
if (fil!=NULL) fclose(fil);
|
|
return(retstat);
|
|
}
|
|
|
|
int configInput(void) {
|
|
char *t;
|
|
char buf[80], nam[16], nbuf[256];
|
|
int i, n, nn, dispFld;
|
|
int retstat;
|
|
char *ext;
|
|
|
|
retstat=-2; /* errors in following section are severe */
|
|
if (tpoint->manual) {
|
|
sprintf(buf, "'%s'", tpoint->device);
|
|
} else {
|
|
sprintf(buf, "%+d ", tpoint->code);
|
|
if (tpoint->code==0) return(0);
|
|
}
|
|
if (table!=NULL && tim>tableTime+60) { my_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 (tpoint==&samp) {
|
|
sens3.present=0;
|
|
sens4.present=0;
|
|
i=sscanf(t, "%12s%d%d", nam, &nn, &n);
|
|
if (i<1) ERR_MSG("missing sensor name");
|
|
ext=".s";
|
|
dispFld=2;
|
|
} else {
|
|
sens1.present=0;
|
|
sens2.present=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";
|
|
dispFld=1;
|
|
}
|
|
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 (!tpoint->manual) { /* set device name */
|
|
str_copy(tpoint->device, nam);
|
|
concatDevice();
|
|
}
|
|
str_append(nam, ext);
|
|
|
|
ERR_I(retstat=instCurve(nam, tpoint->sensor1->ch, dispFld));
|
|
tpoint->sensor1->present=1;
|
|
if (n==2) {
|
|
str_append(nam, "l");
|
|
ERR_I(retstat=instCurve(nam, tpoint->sensor2->ch, dispFld+2));
|
|
tpoint->sensor2->present=1;
|
|
}
|
|
return(0);
|
|
OnError: return(retstat);
|
|
}
|
|
|
|
int loadCache(void) {
|
|
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"));
|
|
ERR_I(putPermanentData(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 presentH, int presentL, float tH, float tL) {
|
|
float p,q;
|
|
|
|
if (presentH) {
|
|
if (presentL) {
|
|
if (tL<tLow) {
|
|
return(tL);
|
|
} else if (tH<tHigh) {
|
|
p=tHigh-tH;
|
|
q=tL-tLow;
|
|
if (p==0.0 && q==0.0) { p=1; q=1; } /* should not be the case */
|
|
return((tL*p*p+tH*q*q)/(p*p+q*q));
|
|
}
|
|
}
|
|
return(tH);
|
|
} else if (presentL) {
|
|
return(tL);
|
|
}
|
|
return(0.0);
|
|
}
|
|
|
|
int LogMinMax(int new) {
|
|
char buf[256], bufs[256];
|
|
int i, j, l, ls, logIt, stat;
|
|
float tol, tmin[2], tmax[2];
|
|
SensorT *s1, *s2;
|
|
|
|
buf[0]='\0';
|
|
|
|
l=0;
|
|
ls=0;
|
|
for (i=1; i<=4; i++) {
|
|
sensor=sensors[i];
|
|
sensor->sMin=0;
|
|
sensor->sMax=0;
|
|
if (sensor->present) {
|
|
assert(l<128);
|
|
sprintf(buf+l, "MDAT?[sens%d.ch]>sens%d.min,sens%d.max;", i, i, i);
|
|
l=strlen(buf);
|
|
assert(ls<128);
|
|
sprintf(bufs+ls, "MDATST?[sens%d.ch]>sens%d.sMin,sens%d.sMax;", i, i, i);
|
|
ls=strlen(bufs);
|
|
}
|
|
}
|
|
if (ls>0) {
|
|
bufs[ls-1]='\0'; /* strip off ';' */
|
|
ERR_P(LscCmd(ser, bufs));
|
|
str_append(buf, "MNMXRST");
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
|
|
/* check for reading errors */
|
|
for (i=1; i<=4; i++) {
|
|
sensor=sensors[i];
|
|
stat=sensor->sMin | sensor->sMax;
|
|
if (stat != sensor->readStat) {
|
|
sensor->readStat=stat;
|
|
if (stat & 1) logfileOut(LOG_MAIN, "invalid reading %s\n", sensor->ch);
|
|
if (stat & 2) logfileOut(LOG_MAIN, "old reading %s\n", sensor->ch);
|
|
if (stat & 12) logfileOut(LOG_MAIN, "unknown reading status %s\n", sensor->ch);
|
|
if (stat & 16) logfileOut(LOG_MAIN, "temp underrange %s\n", sensor->ch);
|
|
if (stat & 32) logfileOut(LOG_MAIN, "temp overrange %s\n", sensor->ch);
|
|
if (stat & 64) logfileOut(LOG_MAIN, "units zero %s\n", sensor->ch);
|
|
if (stat &128) logfileOut(LOG_MAIN, "units overrange %s\n", sensor->ch);
|
|
if (stat==0) logfileOut(LOG_MAIN, "reading o.k. %s\n", sensor->ch);
|
|
}
|
|
}
|
|
|
|
logIt=0;
|
|
for (i=0; i<2; i++) {
|
|
tpoint=tpoints[i];
|
|
s1=tpoint->sensor1;
|
|
s2=tpoint->sensor2;
|
|
tpoint->tMin = WeightedAverage(s1->present, s2->present, s1->min, s2->min) * tpoint->scale;
|
|
tpoint->tMax = WeightedAverage(s1->present, s2->present, s1->max, s2->max) * tpoint->scale;
|
|
}
|
|
sprintf(buf, "@%.3f < T < %.3f K", cryo.tMin, cryo.tMax);
|
|
if (samp.tMax>0.0) {
|
|
sprintf(buf1, "(reg), %.3f < T < %.3f K (samp)", samp.tMin, samp.tMax);
|
|
str_append(buf, buf1);
|
|
}
|
|
logfileOut(LOG_MAIN, "%s\n", buf);
|
|
if (new) {
|
|
mmInt=60;
|
|
} else if (mmInt<600) {
|
|
mmInt=mmInt+60;
|
|
}
|
|
mmTime=tim+mmInt;
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int SetTemp(int switchOn) {
|
|
char *ch;
|
|
float scale;
|
|
|
|
if (switchOn) {
|
|
ERR_I(LogMinMax(1));
|
|
logfileOut(LOG_MAIN, "set %.3f\n", tempC);
|
|
}
|
|
scale=cryo.scale;
|
|
ch=sens1.ch;
|
|
if (sens2.present && tempC<(tLow+tHigh)/2) ch=sens2.ch;
|
|
if (sens3.present) {
|
|
if (controlMode==1) { /* control directly on sample sensor */
|
|
tShift=0;
|
|
ch=sens3.ch;
|
|
if (sens2.present && tempC<(tLow+tHigh)/2) ch=sens4.ch;
|
|
scale=samp.scale;
|
|
} else if (controlMode!=2) {
|
|
tShift=0;
|
|
}
|
|
} else {
|
|
tShift=0;
|
|
}
|
|
str_copy(chan, ch);
|
|
if (scale!=1.0) { /* show set point on display (for rdrn) */
|
|
ERR_P(LscCmd(ser, "LINEAR C,1,0,1,1,[tempC]"));
|
|
}
|
|
if (tShift>maxShift) {
|
|
tShift=maxShift;
|
|
} else if (tShift<-maxShift) {
|
|
tShift=-maxShift;
|
|
}
|
|
tempH=(tempC+tShift)/scale;
|
|
if (tempC==0) {
|
|
ERR_P(LscCmd(ser, "CSET 1:[chan],1,1,0;RANGE:0;SETP 1:0"));
|
|
} else if (remoteMode==1) { /* in local mode: do not switch on heater */
|
|
ERR_P(LscCmd(ser, "SETP 1:[tempH]"));
|
|
} else 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(void) {
|
|
char buf[256];
|
|
int i, l;
|
|
SensorT *sensor;
|
|
|
|
readTemp=0;
|
|
|
|
l=0;
|
|
for (i=1; i<=4; i++) {
|
|
sensor=sensors[i];
|
|
if (sensor->present) {
|
|
assert(l<128);
|
|
sprintf(buf+l, "KRDG?[sens%d.ch]>sens%d.t;", i, i);
|
|
l=strlen(buf);
|
|
} else {
|
|
sensor->t=0.0;
|
|
}
|
|
}
|
|
if (l>0) {
|
|
buf[l-1]='\0'; /* strip off ';' */
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
|
|
cryo.temp=WeightedAverage(sens1.present, sens2.present, sens1.t, sens2.t)*cryo.scale;
|
|
samp.temp=WeightedAverage(sens3.present, sens4.present, sens3.t, sens4.t)*samp.scale;
|
|
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 && remoteMode==2) {
|
|
str_copy(status, "configuring");
|
|
configuring=1;
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int PeriodicTask(void) {
|
|
char buf[256], lbuf[16];
|
|
char *next;
|
|
int i, k;
|
|
time_t putTim;
|
|
float t3[3], p, d, w, t;
|
|
|
|
ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;HTR?>htr;HTRST?>htrst;BUSY?>busy"));
|
|
if (cryo.codDefined && samp.codDefined) {
|
|
per=period; /* no timeout on above command and codes are defined: normal period */
|
|
if (per>logPeriod*1000) per=logPeriod*1000;
|
|
}
|
|
|
|
if (htrst!=htrst0) {
|
|
ERR_I(LogMinMax(0));
|
|
if (htrst<0 || htrst>6) {
|
|
sprintf(buf, "heater status %d\n", htrst);
|
|
logfileOut(LOG_MAIN, buf);
|
|
} else {
|
|
logfileOut(LOG_MAIN, heaterStatus[htrst]);
|
|
}
|
|
htrst0=htrst;
|
|
}
|
|
if (noResp) { /* there was no response on an earlier command, or we are initializing */
|
|
if (!configuring) remoteMode=2;
|
|
LscCmd(ser, "MODE:[remoteMode]");
|
|
k=serialNo; /* check serial number */
|
|
ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo,"));
|
|
if (0!=strcmp(buf1, "LSCI") || 0!=strcmp(buf2, "MODEL340") || serialNo==0) return(0);
|
|
if (k!=serialNo) { /* controller exchanged or we are initializing */
|
|
if (!configuring) {
|
|
str_copy(status, "controller connected");
|
|
}
|
|
if (remoteMode==2) configuring++;
|
|
tempC=0;
|
|
/* reload curve cache: */
|
|
if (cache!=NULL) my_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());
|
|
/* get device names and last codes separated by '/' */
|
|
str_split(buf, cache, '\n'); /* read 1 line */
|
|
samp.device[0]='\0';
|
|
cryo.code=0;
|
|
samp.code=0;
|
|
next=str_split(buf1, buf, '/');
|
|
if (next!=NULL) {
|
|
next=str_split(buf2, next, '/');
|
|
if (next!=NULL) {
|
|
next=str_split(buf3, next, '/');
|
|
cryo.code=atoi(buf3);
|
|
cryo.codChanged=0;
|
|
if (next!=NULL) {
|
|
next=str_split(buf3, next, '\n');
|
|
samp.code=atoi(buf3);
|
|
samp.codChanged=0;
|
|
}
|
|
}
|
|
}
|
|
if (buf1[0]=='*') {
|
|
str_copy(cryo.device, buf1+1);
|
|
cryo.manual=1;
|
|
} else {
|
|
if (cryo.code!=0) str_copy(cryo.device, buf1);
|
|
cryo.manual=0;
|
|
}
|
|
if (buf2[0]=='*') {
|
|
str_copy(samp.device, buf2+1);
|
|
samp.manual=1;
|
|
} else {
|
|
if (samp.code!=0) str_copy(samp.device, buf2);
|
|
samp.manual=0;
|
|
}
|
|
concatDevice();
|
|
if (cryo.manual || cryo.code!=0) { cryo.dirty=1; }
|
|
if (samp.manual || samp.code!=0) { samp.dirty=1; }
|
|
}
|
|
noResp=0;
|
|
}
|
|
|
|
ERR_I(ReadTemp());
|
|
|
|
if (tim>=logTime) {
|
|
i=0;
|
|
if (sens1.present) {
|
|
t3[0]=cryo.temp;
|
|
i=1;
|
|
} else {
|
|
t3[0]=undef;
|
|
}
|
|
if (sens3.present) {
|
|
t3[1]=samp.temp;
|
|
i=2;
|
|
} else {
|
|
if (sens2.present) {
|
|
t3[1]=sens2.t;
|
|
i=2;
|
|
} else {
|
|
t3[1]=undef;
|
|
}
|
|
}
|
|
if (tempC!=0 || htr!=0) {
|
|
t3[2]=htr*htr*power*1e-4;
|
|
i=3;
|
|
} else {
|
|
t3[2]=undef;
|
|
}
|
|
time(&putTim);
|
|
if (i>0) ERR_I(dlog_put_(&putTim, &i, t3));
|
|
logTime=(putTim/logPeriod+1)*logPeriod;
|
|
if (tim>mmTime) ERR_I(LogMinMax(0));
|
|
}
|
|
if (sens1.present && sens3.present && controlMode==2 && tempC!=0) {
|
|
t=sens1.t;
|
|
if (sens2.present && tempC<(tLow+tHigh)/2) t=sens2.t;
|
|
d=(tempH-t)/t-1.0; /* relative difference */
|
|
w=exp(-d*d*230); /* gaussian */
|
|
if (w<0.1) tInt=0; /* reset when far from setpoint (more than 10 %) */
|
|
if (int2<1) int2=1;
|
|
if (tInt<int2*1000/per) tInt+=w; /* increase integral time until int2 sec. */
|
|
if (tInt>w) {
|
|
p=w/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++) {
|
|
tpoint=tpoints[i];
|
|
if (tpoint->code1!=tpoint->code) { /* code has changed -> wait for a confirmation */
|
|
tpoint->code=tpoint->code1;
|
|
tpoint->codChanged=1;
|
|
} else {
|
|
if (tpoint->codChanged) { /* code change confirmed */
|
|
tpoint->codChanged=0;
|
|
Progress(1);
|
|
if (tpoint->code1==0) {
|
|
logfileOut(LOG_MAIN, "%s unplugged\n", tpoint->tname);
|
|
} else {
|
|
logfileOut(LOG_MAIN, "plugged %d on %s\n", tpoint->code1, tpoint->tname);
|
|
}
|
|
tpoint->manual=0;
|
|
tempC=0;
|
|
remoteMode=2; /* set to remote mode */
|
|
LscCmd(ser, "MODE:[remoteMode]");
|
|
tpoint->dirty=1;
|
|
if (!configuring) configuring=1;
|
|
}
|
|
tpoint->codDefined=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (key!=0) {
|
|
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;
|
|
remoteMode=1;
|
|
ERR_P(LscCmd(ser, "MODE?>remoteMode"));
|
|
if (remoteMode==2) { /* user switched to remote mode */
|
|
ERR_P(LscCmd(ser, "PID?1>prop,integ,deriv"));
|
|
if (controlMode==2) {
|
|
ERR_P(LscCmd(ser, "RANGE?>iRange"));
|
|
if (iRange==0) tempC=0;
|
|
} else {
|
|
ERR_P(LscCmd(ser, "RANGE?>iRange;SETP?1>tempC"));
|
|
}
|
|
setFlag=(iRange>0);
|
|
}
|
|
}
|
|
|
|
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 inputSettings(Testpoint *this) {
|
|
|
|
tpoint=this;
|
|
if (tpoint->dirty && samp.codDefined) {
|
|
if (busy==0 || cryo.dirty>=0 && tpoint->dirty>=0) { /* do not enter when busy and cryo.dirty/P indicates error on last time */
|
|
if (tpoint->manual) {
|
|
logfileOut(LOG_MAIN ,"configure %s inputs for %s\n", tpoint->tname, tpoint->device);
|
|
} else {
|
|
if (tpoint->code==0) {
|
|
logfileOut(LOG_MAIN ,"reset %s inputs\n", tpoint->tname);
|
|
} else {
|
|
logfileOut(LOG_MAIN ,"configure %s inputs for code %+d\n", tpoint->tname, tpoint->code);
|
|
}
|
|
}
|
|
if (tpoint->dirty>0) tpoint->try=0;
|
|
tpoint->sensor1->present=0;
|
|
tpoint->sensor2->present=0;
|
|
if (!tpoint->manual) { tpoint->device[0]='\0'; concatDevice(); }
|
|
tpoint->dirty=configInput();
|
|
if (tpoint->dirty<0) {
|
|
tpoint->try++;
|
|
if (tpoint->dirty!=-1 || tpoint->try>3) {
|
|
logfileShowErr("fatal error");
|
|
tpoint->dirty=0; tpoint->device[0]='\0'; concatDevice();
|
|
} else {
|
|
logfileShowErr("try again");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int SetPower(void) {
|
|
int i, j;
|
|
float pa, pr, pw, dif;
|
|
|
|
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_MAIN, "power %f\n", power, iAmp, iRange);
|
|
ERR_P(LscCmd(ser, "CDISP 1:1,[resist],1;MOUT 1:0;CMODE 1:1"));
|
|
ERR_P(LscCmd(ser, "CLIMIT 1:[tLimit],0,0,[iAmp],[iRange]"));
|
|
ERR_I(SetTemp(1));
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int Display(void) {
|
|
char flds[6], fmt[6], buf[256];
|
|
int i,k,l;
|
|
SensorT *s;
|
|
|
|
maxfld=0;
|
|
k=1;
|
|
flds[0]='*';
|
|
flds[5]='\0';
|
|
for (i=1; i<=4; i++) { /* fill in kelvin fields */
|
|
s=sensors[i];
|
|
if (s->present) {
|
|
flds[k]=s->ch[0];
|
|
fmt[k]='1';
|
|
if (k>maxfld) maxfld=k;
|
|
} else {
|
|
flds[k]='\0';
|
|
}
|
|
k=k+2; if (k>4) k=2;
|
|
}
|
|
|
|
for (i=1; i<=4; i++) { /* fill in raw fields */
|
|
s=sensors[i];
|
|
if (s->present) {
|
|
k=strlen(flds); /* find next free field */
|
|
if (k<=4) {
|
|
if (k>maxfld) maxfld=k;
|
|
flds[k]=s->ch[0];
|
|
fmt[k]='3';
|
|
}
|
|
}
|
|
}
|
|
|
|
/* fields 5-8 standard raw data */
|
|
ERR_P(LscCmd(ser, "DISPFLD 5,A,3;DISPFLD 6,C,3;DISPFLD 7,B,3;DISPFLD 8,D,3"));
|
|
if (maxfld==0) { /* show raw data */
|
|
ERR_P(LscCmd(ser, "DISPFLD 1,A,3;DISPFLD 2,C,3;DISPFLD 3,B,3;DISPFLD 4,D,3;DISPLAY:4"));
|
|
} else {
|
|
l=0;
|
|
for (k=1; k<=maxfld; k++) {
|
|
if (flds[k]!='\0') {
|
|
assert(l<128);
|
|
sprintf(buf+l, "DISPFLD %d,%c,%c;", k, flds[k], fmt[k]);
|
|
l=strlen(buf);
|
|
}
|
|
}
|
|
str_append(buf, "DISPLAY:[maxfld]");
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int Settings(void) {
|
|
char nbuf[256], buf[256], *cfg, *p;
|
|
char alarms[3];
|
|
|
|
cfg=NULL;
|
|
if (cryo.dirty && cryo.codDefined || samp.dirty && samp.codDefined) {
|
|
|
|
ERR_I(inputSettings(&cryo));
|
|
ERR_I(inputSettings(&samp));
|
|
|
|
ERR_P(LscCmd(ser, "ALARM A:0;ALARM B:0;ALARM C:0;ALARM D:0"));
|
|
|
|
alarms[0]='\0';
|
|
alarms[1]='\0';
|
|
alarms[2]='\0';
|
|
if (sens1.present) {
|
|
ERR_I(SetPower());
|
|
str_copy(buf, "ALARM [sens1.ch]:1,1,[tLimit],0,0,1;RELAY 1:1;BEEP:0");
|
|
alarms[0]=sens1.ch[0];
|
|
if (sens3.present) {
|
|
str_append(buf, ";ALARM [sens3.ch]:1,1,[tLimit],0,0,1");
|
|
alarms[1]=sens3.ch[0];
|
|
}
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
|
|
/* switch of unused channels */
|
|
buf[0]='\0';
|
|
if (NULL==strchr(alarms, 'A')) str_append(buf, ";ALARM A:0");
|
|
if (NULL==strchr(alarms, 'B')) str_append(buf, ";ALARM B:0");
|
|
if (NULL==strchr(alarms, 'C')) str_append(buf, ";ALARM C:0");
|
|
if (NULL==strchr(alarms, 'D')) str_append(buf, ";ALARM D:0");
|
|
if (buf[0]!='\0') ERR_P(LscCmd(ser, buf+1)); /* send without leading semicolon */
|
|
|
|
ERR_I(Display());
|
|
|
|
str_copy(nbuf, binDir);
|
|
str_append(nbuf, cryo.device);
|
|
str_append(nbuf, ".cfg");
|
|
cfg=str_read_file(nbuf);
|
|
if (cfg!=NULL) {
|
|
logfileOut(LOG_MAIN, "%s opened\n", nbuf);
|
|
p=str_split(buf, cfg, '\n');
|
|
sscanf(buf, "%f%f", &cryo.scale, &samp.scale);
|
|
while (p!=NULL) {
|
|
p=str_split(buf, p, '\n');
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
my_free(cfg);
|
|
}
|
|
|
|
ERR_I(ReadTemp());
|
|
}
|
|
return(0);
|
|
OnError:
|
|
if (cfg!=NULL) my_free(cfg);
|
|
return(-1);
|
|
}
|
|
|
|
int ExecuteRequest(void) {
|
|
char *t, *res;
|
|
struct CocClient *client;
|
|
float p;
|
|
|
|
if (readTemp) ERR_I(ReadTemp());
|
|
if (remoteMode==2) ERR_I(Settings());
|
|
if (powerFlag) {
|
|
powerFlag=0;
|
|
ERR_I(SetPower());
|
|
}
|
|
if (pidFlag) {
|
|
pidFlag=0;
|
|
ERR_P(LscCmd(ser,"PID 1:[prop],[integ],[deriv]"));
|
|
}
|
|
if (setFlag) {
|
|
setFlag=0;
|
|
if (sens1.present) {
|
|
tInt=0; /* reset integral time */
|
|
ERR_I(SetTemp(1));
|
|
}
|
|
}
|
|
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) {
|
|
tempC=0;
|
|
remoteMode=2; /* set to remote mode */
|
|
ERR_P(LscCmd(ser, "MODE:[remoteMode]"));
|
|
if (!configuring) {
|
|
str_copy(status, "configuring");
|
|
configuring=1;
|
|
}
|
|
t=strchr(device, '/');
|
|
if (t==NULL) {
|
|
if (0==strcmp(device, "0") || 0==strcasecmp(device, "auto")) {
|
|
cryo.manual=0; cryo.dirty=1; cryo.device[0]='\0';
|
|
samp.manual=0; samp.dirty=1; samp.device[0]='\0';
|
|
} 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;
|
|
|
|
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>4) {
|
|
logfileOut(LOG_MAIN ,"%d cycles lost\n", tdif-1);
|
|
}
|
|
|
|
ERR_I(PeriodicTask());
|
|
if (remoteMode==2) ERR_I(Settings());
|
|
|
|
return(0);
|
|
OnError:
|
|
if (0==strcmp(ErrMessage, "timeout")) {
|
|
if (noResp==1) { /* this is the second time we have no response */
|
|
per=period+15000; /* long period if no response */
|
|
cryo.temp=0;
|
|
samp.temp=0;
|
|
remoteMode=1;
|
|
configuring=0;
|
|
} else {
|
|
logfileOut(LOG_ALL ,"no response\n");
|
|
noResp=1;
|
|
per=100; /* try again soon */
|
|
}
|
|
return(0);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{ int logIt=0;
|
|
int i, iret, cntError, use_stdout=0;
|
|
char *host;
|
|
char buf[256], opt;
|
|
int port, msecTmo;
|
|
|
|
str_copy(cryo.tname,"main");
|
|
str_copy(sens1.ch,"A");
|
|
str_copy(sens2.ch,"B");
|
|
str_copy(samp.tname,"sample stick");
|
|
str_copy(sens3.ch,"C");
|
|
str_copy(sens4.ch,"D");
|
|
cryo.codChanged=1;
|
|
cryo.scale=1.0;
|
|
samp.codChanged=1;
|
|
samp.scale=1.0;
|
|
|
|
logMask=LOG_MAIN;
|
|
binDir="bin/";
|
|
logDir="log/";
|
|
serverId="tecs";
|
|
host="lnsp26:4000/0";
|
|
port=0;
|
|
msecTmo=0;
|
|
logfileOut(LOG_MAIN ,"%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 if ('f'==opt) {
|
|
i++;
|
|
logPeriod=atoi(argv[i]);
|
|
} else {
|
|
logfileOut(LOG_MAIN ,"?");
|
|
}
|
|
if (opt!=' ') logfileOut(LOG_MAIN ,"-%c ", opt);
|
|
logfileOut(LOG_MAIN ,"%s ", argv[i]);
|
|
}
|
|
}
|
|
if (port==0) port=9753;
|
|
if (msecTmo==0) msecTmo=1000;
|
|
if (logPeriod==0) logPeriod=5;
|
|
|
|
str_copy(buf, logDir);
|
|
str_append(buf, serverId);
|
|
|
|
str_copy(status, "starting up");
|
|
logfileStatusBuf(status);
|
|
logfile=logfileInit(buf, logIt, use_stdout, logIt && use_stdout);
|
|
logfileOut(LOG_MAIN ,"\n");
|
|
logfileWrite(logMask);
|
|
|
|
ERR_I(CocInitServer(1024, port));
|
|
|
|
CocDefStruct(cryo, Testpoint);
|
|
CocDefStruct(samp, Testpoint);
|
|
CocDefPtr(tpoint, Testpoint);
|
|
|
|
CocFltFld(Testpoint, temp, CocRD);
|
|
CocFltFld(Testpoint, scale, CocRD);
|
|
CocFltFld(Testpoint, tMin, CocRD);
|
|
CocFltFld(Testpoint, tMax, CocRD);
|
|
|
|
CocDefStruct(sens1, SensorT);
|
|
CocDefStruct(sens2, SensorT);
|
|
CocDefStruct(sens3, SensorT);
|
|
CocDefStruct(sens4, SensorT);
|
|
CocDefPtr(sensor, SensorT);
|
|
|
|
CocFltFld(SensorT, t, CocRD);
|
|
CocFltFld(SensorT, min, CocRD);
|
|
CocFltFld(SensorT, max, CocRD);
|
|
CocIntFld(SensorT, readStat, CocRD);
|
|
CocIntFld(SensorT, sMin, CocRD);
|
|
CocIntFld(SensorT, sMax, CocRD);
|
|
CocStrFld(SensorT, ch, CocRD);
|
|
|
|
CocDefFlt(htr, CocRD);
|
|
CocDefFlt(power, powerFlag);
|
|
CocDefFlt(prop, pidFlag);
|
|
CocDefFlt(integ, pidFlag);
|
|
CocDefFlt(deriv, pidFlag);
|
|
CocDefFlt(tempC, setFlag);
|
|
CocDefFlt(tempH, CocRD);
|
|
CocDefFlt(tLimit, CocRD);
|
|
CocDefFlt(maxShift, CocWR);
|
|
|
|
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);
|
|
CocDefStr(dlogfile, CocRD);
|
|
CocDefStr(logfile, 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(remoteMode, CocRD);
|
|
CocDefInt(htrst, CocRD);
|
|
|
|
CocDefInt(logPeriod, CocWR);
|
|
CocDefInt(readTemp, CocWR);
|
|
CocDefInt(controlMode, CocWR);
|
|
CocDefInt(int2, CocWR);
|
|
CocDefInt(busy, CocRD);
|
|
CocDefInt(serialNo, CocRD);
|
|
CocDefInt(configuring, CocRD);
|
|
CocDefInt(quit, CocWR);
|
|
|
|
CocAlias(tempX,cryo.temp);
|
|
CocAlias(tempP,samp.temp);
|
|
CocAlias(tX,cryo.temp);
|
|
CocAlias(tS,samp.temp);
|
|
CocAlias(t1,sens1.t);
|
|
CocAlias(t2,sens2.t);
|
|
CocAlias(t3,sens3.t);
|
|
CocAlias(t4,sens4.t);
|
|
CocAlias(set,tempC);
|
|
CocAlias(int,integ);
|
|
|
|
ERR_P(ser=SerOpen(host, msecTmo, idleHdl));
|
|
ERR_I(iret=CocHandleRequests(100, 0));
|
|
ftime(&tim0);
|
|
tim=tim0.time;
|
|
if (period>1000) { /* round time */
|
|
tim0.time=tim0.time-(tim0.time % (period/1000));
|
|
tim0.millitm=0;
|
|
}
|
|
str_copy(dlogfile, logDir);
|
|
str_append(dlogfile, serverId);
|
|
str_append(dlogfile, ".dlog");
|
|
logfileOut(LOG_MAIN, "open data log file: %s\n", dlogfile);
|
|
ERR_I(iret=dlog_open_write_(dlogfile));
|
|
if (iret==1) logfileOut(LOG_MAIN, "created new data log file\n");
|
|
logfileWrite(logMask);
|
|
|
|
remoteMode=2;
|
|
LscCmd(ser, "MODE?>remoteMode");
|
|
prop=50;
|
|
integ=20;
|
|
deriv=0;
|
|
LscCmd(ser, "PID?1>prop,integ,deriv");
|
|
if (remoteMode!=2) configuring=0;
|
|
per=1; /* advance fast when initializing */
|
|
cntError=0;
|
|
while (!quit) {
|
|
iret=mainBody();
|
|
if (iret<0) {
|
|
cntError++;
|
|
if (cntError>10) ERR_MSG("too many errors - quit");
|
|
logfileShowErr("error in TecsServer/mainBody");
|
|
} else {
|
|
if (cntError>0) cntError--;
|
|
}
|
|
}
|
|
LogMinMax(0);
|
|
logfileWrite(logMask);
|
|
ERR_MSG("got quit command");
|
|
OnError:
|
|
logfileShowErr("exit TecsServer");
|
|
dlog_close_w_();
|
|
SerClose(ser);
|
|
CocCloseServer();
|
|
return(0);
|
|
}
|