2494 lines
63 KiB
C
2494 lines
63 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "myc_mem.h"
|
|
#include "myc_err.h"
|
|
#include "coc_util.h"
|
|
#include "coc_server.h"
|
|
#include "coc_logfile.h"
|
|
#include "myc_str.h"
|
|
#include "myc_time.h"
|
|
#include "tecs_lsc.h"
|
|
#include "tecs_data.h"
|
|
|
|
/* --- non ANSI signal --- */
|
|
#ifndef SIGPIPE
|
|
#define SIGPIPE 13
|
|
#endif
|
|
|
|
#define TABLE_FILE "tecs.cfg"
|
|
#define LOGLIFETIME 24*3600
|
|
|
|
static SerChannel *ser=NULL;
|
|
static char binDir[256]="";
|
|
static char logDir[256]="";
|
|
static int logIt=0, use_stdout=0;
|
|
static char serverId[32]="tecs";
|
|
static int msecTmo=5000;
|
|
static char host[64]="";
|
|
static int port=9753;
|
|
|
|
typedef struct {
|
|
char ch[4];
|
|
float t, t0, t1, t2, min, max, band; /* temperatures */
|
|
float scale; /* scale for extreme ranges */
|
|
float lim; /* range limit (used when two sensors present) */
|
|
float alarm;
|
|
int stat1, stat2; /* reading status summary */
|
|
int present; /* 0: sensor inactive, 1: sensor configured, -1: sensor parameters read */
|
|
int readStat; /* reading status */
|
|
char type;
|
|
} SensorT;
|
|
|
|
enum Sensors { A, B, C, D, A1, A2, A3, A4, N_SENSORS };
|
|
|
|
static SensorT
|
|
sensA={"A"},
|
|
sensB={"B"},
|
|
sensC={"C"},
|
|
sensD={"D"},
|
|
sensA1={"A1", DATA_UNDEF},
|
|
sensA2={"A2", DATA_UNDEF},
|
|
sensA3={"A3", DATA_UNDEF},
|
|
sensA4={"A4", DATA_UNDEF},
|
|
*sensors[N_SENSORS]={&sensA, &sensB, &sensC, &sensD, &sensA1, &sensA2, &sensA3, &sensA4 },
|
|
*ctlSens=NULL, /* control sensor */
|
|
*heliumSens=NULL,
|
|
*auxSens=NULL,
|
|
*testSens=NULL,
|
|
*sens=&sensA;
|
|
|
|
typedef struct {
|
|
SensorT *sensor1, *sensor2;
|
|
float temp; /* weighted temperature */
|
|
float t1, t2; /* minimum and maximum temperatures since ... */
|
|
} Testpoint;
|
|
|
|
static Testpoint /* C standard guarantees initialization to zero */
|
|
cryo, /* data for heat exchanger, or the only sensors */
|
|
samp, /* data for sensors on sample stick */
|
|
*tpoints[2]={&cryo, &samp},
|
|
*tpoint=&cryo;
|
|
|
|
typedef struct _Plug {
|
|
SensorT *sensor1, *sensor2;
|
|
int manual; /* manual device */
|
|
int code, code1, code2; /* device code, buffers for device code */
|
|
int codChanged; /* code has changed */
|
|
int codDefined; /* code is not yet confirmed */
|
|
char device[16]; /* device name */
|
|
} Plug;
|
|
|
|
static Plug
|
|
plug0={&sensA, &sensB }, /* data for sensors on plug0 */
|
|
plug1={&sensC, &sensD }, /* data for sensors on plug1 */
|
|
*plugs[2]={&plug0, &plug1},
|
|
*plug=&plug0;
|
|
|
|
static float
|
|
set, /* set T */
|
|
setH, /* set T on heat exchanger */
|
|
htr, power=DATA_UNDEF, /* heater current percentage, heater power */
|
|
tLimit, /* temperature limit */
|
|
maxPower, /* max. Power */
|
|
scalPower,
|
|
powFact=1, /* power factor (for external power supplies) */
|
|
resist, /* heater resistance */
|
|
tShift=0, /* setpoint shift */
|
|
full, /* full value for helium level */
|
|
prop, integ, deriv, /* pid */
|
|
maxShift=2, /* maximal shift in when controlMode=2 */
|
|
tm=DATA_UNDEF, /* main temperature */
|
|
ts=DATA_UNDEF, /* sample temperature */
|
|
tr=DATA_UNDEF, /* set temperature (read back) */
|
|
te=DATA_UNDEF, /* test temperature */
|
|
he=DATA_UNDEF, /* helium level value */
|
|
aux=DATA_UNDEF, /* auxiliary value */
|
|
ramp=0,
|
|
slope=0,
|
|
smooth=0,
|
|
fbuf, /* float buffer */
|
|
r1, r2, /* temporary values */
|
|
still=0,
|
|
tInt=0; /* integral time (sec.) for setpoint shift */
|
|
|
|
static int
|
|
logPeriod=5, /* data logging period (sec.) */
|
|
period=5000, /* default read interval (msec.) */
|
|
logTime, /* next logging time */
|
|
settingsFlag, /* settings to be done */
|
|
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 */
|
|
int2=30, /* inegration time for controlMode 2 */
|
|
remoteMode, /* 1: local, 2: remote */
|
|
maxfld, /* last used display field */
|
|
busy, /* busy after CRVSAV */
|
|
relay, relay0, /* relay status */
|
|
deviceFlag, /* device given via net */
|
|
num, /* curve number */
|
|
key, /* key status */
|
|
serialNo,
|
|
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 */
|
|
loop=1, /* active loop */
|
|
touched, /* user touched keys */
|
|
tim0, /* msec Time */
|
|
per, /* effective period */
|
|
mmInt, mmTime, /* interval and time for next min-max logging */
|
|
nScan=0, /* number of scanned channels */
|
|
alarmListSize=0,
|
|
lockAlarm,
|
|
cntError,
|
|
tableTime; /* last time when table was read */
|
|
|
|
int tim, rdTim; /* actual time, read Time */
|
|
|
|
static int decod[8]={21,20,17,16,5,4,1,0}; /* for code conversion */
|
|
|
|
static char
|
|
statusBuf[132], /* phase status */
|
|
status[1000], /* status summary */
|
|
pid[128], /* PID summary */
|
|
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[4], /* actual channel */
|
|
alarmStatus[20], /* alarm status */
|
|
config[256], /* special configuration commands */
|
|
helium[80], /* helium level status */
|
|
heUnits[4], /* helium level units */
|
|
alarmChannels[N_SENSORS],
|
|
alarmHistory[N_SENSORS],
|
|
controlChannel[4]="A";
|
|
|
|
static char
|
|
*alarmList[N_SENSORS], /* enabled alarms */
|
|
*table=NULL, /* environment devices table */
|
|
*cache=NULL, /* curve list cache */
|
|
*logfile="<none>";
|
|
|
|
static int logMask=LOG_MAIN;
|
|
|
|
static float gradata[7200];
|
|
static char grapar[128];
|
|
static int* grasize;
|
|
|
|
typedef struct {
|
|
char cmd[COC_CMD_LEN];
|
|
int logstart;
|
|
long int logpos;
|
|
char logline[COC_RES_LEN];
|
|
} ClientData;
|
|
|
|
/*
|
|
static ClientData clInit;
|
|
static ClientData *clData=&clInit;
|
|
*/
|
|
|
|
static ClientData *clData;
|
|
|
|
void ignore_forever(int signo) {
|
|
signal(signo,ignore_forever);
|
|
}
|
|
|
|
int IdleHdl(int tmo, int fd) {
|
|
int iRet;
|
|
|
|
iRet=CocHandleRequests(tmo, fd);
|
|
if (iRet<0) logfileShowErr("CocHandleRequests");
|
|
return iRet;
|
|
}
|
|
|
|
void *SetClientData(void *data) {
|
|
ClientData *cl;
|
|
if (data==NULL) {
|
|
NEW(cl, ClientData);
|
|
return cl;
|
|
}
|
|
clData = data;
|
|
return NULL;
|
|
OnError:
|
|
return NULL;
|
|
}
|
|
|
|
void ConcatDevice(void) {
|
|
str_copy(device, plug0.device);
|
|
if (0!=strcmp(plug0.device, plug1.device) && (plug1.device[0]!='\0' || plug1.manual)) {
|
|
str_append(device, "/");
|
|
str_append(device, plug1.device);
|
|
}
|
|
if (device[0]=='\0') return;
|
|
if (plug0.manual) {
|
|
str_append(device, " (manual");
|
|
} else {
|
|
str_append(device, " (auto");
|
|
}
|
|
if (plug1.manual==plug0.manual) {
|
|
str_append(device, ")");
|
|
} else if (plug1.manual) {
|
|
str_append(device, "/manual)");
|
|
} else {
|
|
str_append(device, "/auto)");
|
|
}
|
|
}
|
|
|
|
int PutPermanentData(FILE *fil) {
|
|
char buf[256];
|
|
char *d1, *d2;
|
|
|
|
if (plug0.manual) {
|
|
d1="*";
|
|
} else {
|
|
d1="";
|
|
}
|
|
if (plug1.manual) {
|
|
d2="*";
|
|
} else {
|
|
d2="";
|
|
}
|
|
sprintf(buf, "%s%s/%s%s/%d/%d\n", d1, plug0.device, d2, plug1.device, plug0.code, plug1.code);
|
|
ERR_SI(fputs(buf, fil));
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int InstalCurve(SensorT *sensor, char *dev) {
|
|
/*
|
|
install sensor
|
|
*/
|
|
char nam[32], 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;
|
|
|
|
sens=sensor;
|
|
str_copy(chan, sens->ch);
|
|
sens->present=0;
|
|
if (sens->type=='x' || sens->type=='h' || sens->type=='f') {
|
|
if (chan[0]>='C') {
|
|
ERR_P(LscCmd(ser, "INTYPE [chan]:0,1,2,1,13;INSET [chan],1")); /* 7.5 V Range */
|
|
} else {
|
|
ERR_P(LscCmd(ser, "INTYPE [chan]:0,1,2,1,12;INSET [chan],1")); /* 5 V Range */
|
|
}
|
|
if (sens->type=='f') {
|
|
ERR_P(LscCmd(ser, "MNMX [chan]:1,4;INCRV [chan]:0"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "MNMX [chan]:1,3;INCRV [chan]:0"));
|
|
}
|
|
if (settingsFlag==0) sens->present=1;
|
|
return 0;
|
|
}
|
|
|
|
fil=NULL;
|
|
crv=NULL;
|
|
e=NULL;
|
|
|
|
sprintf(nam, "%s_%c", dev, sens->type);
|
|
logfileOut(LOG_MAIN+LOG_STAT, "install curve %s\n", nam);
|
|
|
|
/* read curve file */
|
|
str_copy(nbuf, binDir);
|
|
str_append(nbuf, nam);
|
|
str_append(nbuf, ".crv");
|
|
|
|
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=MALLOC(1)); *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");
|
|
|
|
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");
|
|
|
|
ERR_P(LscCmd(ser, "CRVHDR?[num]>head"));
|
|
|
|
e=strchr(entry, '\n');
|
|
if (e!=NULL) { *e='\0'; e++; }
|
|
}
|
|
}
|
|
if (head[0]!='\0' && LscEqPar(head, chead)) { /* header matches: select sensor type and curve */
|
|
|
|
if (chan[1]>'1') { /* scanned inputs A2...A4 */
|
|
ERR_P(LscCmd(ser, "INCRV?[chan]>buf2;INSET?[chan]>buf3"));
|
|
str_copy(buf1, intype);
|
|
} else {
|
|
ERR_P(LscCmd(ser, "INTYPE?[chan]>buf1;INCRV?[chan]>buf2;INSET?[chan]>buf3"));
|
|
}
|
|
if (!LscEqPar(buf1, intype) || atoi(buf2)!=num || buf3[0]!='1') {
|
|
ERR_P(LscCmd(ser, "ANALOG 2:0,3;INSET [chan],1"));
|
|
if (chan[1]<='1') ERR_P(LscCmd(ser, "RANGE:0;INTYPE [chan]:[intype]"));
|
|
ERR_P(LscCmd(ser, "INCRV [chan]:[num];MNMX [chan]:1,1"));
|
|
logfileOut(LOG_MAIN, "curve %d on channel %s selected\n", num, chan);
|
|
} else {
|
|
logfileOut(LOG_MAIN, "curve %d on channel %s is already selected\n", num, chan);
|
|
}
|
|
|
|
} else { /* header does not match -> download */
|
|
|
|
logfileOut(LOG_MAIN, "%s\n%s\n", head, chead);
|
|
if (num<=20) ERR_MSG("standard curve does not match");
|
|
if (busy) ERR_MSG("busy");
|
|
logfileOut(LOG_MAIN+LOG_STAT, "download curve %d\n", num);
|
|
ERR_P(LscCmd(ser, "ANALOG 2:0,3;INSET [chan],1"));
|
|
/* select sensor type first */
|
|
if (chan[1]<='1') ERR_P(LscCmd(ser, "RANGE:0;INTYPE [chan]:[intype]"));
|
|
|
|
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");
|
|
|
|
/* store header, but without name (curve format must be determined before loading points) */
|
|
t=strchr(chead, ',');
|
|
if (t==NULL) ERR_MSG("illegal header");
|
|
str_copy(buf2, t);
|
|
ERR_P(LscCmd(ser, "CRVHDR [num]:[buf2]"));
|
|
|
|
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++;
|
|
sprintf(statusBuf, "downloading curve %d at line %d", num, i);
|
|
}
|
|
points=t;
|
|
} while (t!=NULL);
|
|
|
|
/* write header, select curve */
|
|
str_upcase(head, chead);
|
|
ERR_P(LscCmd(ser, "CRVHDR [num]:[head];INCRV [chan]:[num];MNMX [chan]:1,1"));
|
|
logfileOut(LOG_MAIN, "curve %d selected on channel %s\n", num, chan);
|
|
saveTime=tim+30;
|
|
}
|
|
FREE(crv); crv=NULL;
|
|
|
|
if (sens->scale!=1.0)
|
|
ERR_P(LscCmd(ser, "LINEAR [chan]:1,[sens.scale],1,1,0")); /* scaling for display */
|
|
|
|
if (settingsFlag==0) sens->present=1;
|
|
/*
|
|
if (num<=20) return 0;
|
|
*/
|
|
/* standard curve, do not touch cache */
|
|
|
|
/* rewrite cache with actual entry at beginning */
|
|
str_copy(nbuf, logDir);
|
|
str_append(nbuf, "lsc.tmp");
|
|
fil=fopen(nbuf, "w+");
|
|
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 */
|
|
if (num>20) {
|
|
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));
|
|
str_copy(buf, logDir);
|
|
sprintf(lbuf, "lsc.%d", serialNo);
|
|
str_append(buf, lbuf);
|
|
rename(nbuf, buf); /* rename to permanent version */
|
|
fil=NULL;
|
|
FREE(cache);
|
|
/* re-read it */
|
|
ERR_P(cache=str_read_file(buf));
|
|
|
|
/* for vms: */
|
|
str_append(buf, ";-1");
|
|
remove(buf); /* remove old version */
|
|
buf[strlen(buf)-2]='\0'; /* strip off "-1" */
|
|
rename(buf, buf); /* lower version number */
|
|
|
|
return 0;
|
|
|
|
OnError:
|
|
if (crv!=NULL) FREE(crv);
|
|
if (fil!=NULL) fclose(fil);
|
|
return -1;
|
|
}
|
|
|
|
int PrepInput(char *label) {
|
|
char *t, *e;
|
|
char nam[16], chans[8], nbuf[256], typ;
|
|
int i, j, l;
|
|
SensorT *s;
|
|
|
|
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;
|
|
}
|
|
t=strstr(table, label);
|
|
if (t==NULL) ERR_MSG("device not found");
|
|
e=strchr(t, '\'');
|
|
if (e==NULL || e>strchr(t,'\n')) ERR_MSG("missing ' or device name in table file");
|
|
t=e+1;
|
|
if (plug==&plug0) {
|
|
sensA.present=0;
|
|
sensB.present=0;
|
|
sensA.scale=1;
|
|
sensB.scale=1;
|
|
sensA.lim=0;
|
|
sensB.lim=0;
|
|
sensA.alarm=0;
|
|
sensB.alarm=0;
|
|
slope=0;
|
|
ramp=0;
|
|
controlMode=0;
|
|
powFact=1;
|
|
config[0]='\0';
|
|
tLimit=310;
|
|
} else {
|
|
sensC.present=0;
|
|
sensD.present=0;
|
|
sensC.scale=1;
|
|
sensD.scale=1;
|
|
sensC.lim=0;
|
|
sensD.lim=0;
|
|
sensC.alarm=0;
|
|
sensD.alarm=0;
|
|
}
|
|
loop=1;
|
|
resist=10;
|
|
str_copy(heUnits, "%");
|
|
|
|
i=sscanf(t, "%12s%n", nam, &l);
|
|
if (i<1) ERR_MSG("missing device name");
|
|
nam[strlen(nam)-1]='\0'; /* strip off quote */
|
|
t+=l;
|
|
str_copy(chans, "____");
|
|
i=sscanf(t, "%8s%n", chans, &l);
|
|
if (i<1) ERR_MSG("missing chans");
|
|
t+=l;
|
|
|
|
/* interprete settings until '+' appeares */
|
|
ERR_P(CocReadVars(t, '+'));
|
|
|
|
if (loop!=2) loop=1;
|
|
if (strlen(chans)>4) ERR_MSG("no more than 4 channels allowed");
|
|
|
|
j=0;
|
|
if (plug==&plug1) j=2;
|
|
|
|
if (chans[0]>'0' && chans[0]<='4') {
|
|
nScan=chans[0]-'0';
|
|
for (i=4;i<4+nScan;i++) {
|
|
s=sensors[i];
|
|
s->present=-1;
|
|
s->band=10;
|
|
if (s->scale==0.0) s->scale=1.0;
|
|
s->type='1'+i-4;
|
|
}
|
|
chans[0]='_';
|
|
for (i=4+nScan; i<N_SENSORS; i++) {
|
|
sensors[i]->t=DATA_UNDEF;
|
|
sensors[i]->present=0;
|
|
}
|
|
}
|
|
for (i=j; i<j+2; i++) {
|
|
s=sensors[i];
|
|
typ=chans[i];
|
|
if (typ=='_') typ='\0';
|
|
if (NULL==strchr("mnslhxft", typ)) ERR_MSG("unknown channel type code");
|
|
if (typ!='\0') {
|
|
s->present=-1;
|
|
}
|
|
s->type=typ;
|
|
s->band=10;
|
|
if (s->scale==0.0) s->scale=1.0;
|
|
if (s->alarm==0.0 && typ=='m' || typ=='s') s->alarm=tLimit;
|
|
}
|
|
|
|
if (!plug->manual) { /* set device name */
|
|
str_copy(plug->device, nam);
|
|
ConcatDevice();
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
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);
|
|
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 an 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(float tH, float tL, Testpoint *t) {
|
|
float p,q, tLow, tHigh;
|
|
SensorT *s1, *s2;
|
|
|
|
if (tH==DATA_UNDEF) tH=0.0;
|
|
if (tL==DATA_UNDEF) tL=0.0;
|
|
s1=t->sensor1;
|
|
s2=t->sensor2;
|
|
tH = tH * s1->scale;
|
|
tL = tL * s2->scale;
|
|
if (tH!=0.0) {
|
|
if (tL!=0.0) {
|
|
tLow=s1->lim;
|
|
tHigh=s2->lim;
|
|
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 (tL!=0.0) {
|
|
return tL ;
|
|
}
|
|
return DATA_UNDEF;
|
|
}
|
|
|
|
void LogMinMax(int new) {
|
|
char buf[256];
|
|
int i;
|
|
static int first;
|
|
float tbuf;
|
|
SensorT *s1, *s2;
|
|
|
|
sprintf(buf, "@");
|
|
if (cryo.sensor1!=NULL) { /* at least one sensor is present */
|
|
for (i=0; i<2; i++) {
|
|
tpoint=tpoints[i];
|
|
s1=tpoint->sensor1;
|
|
s2=tpoint->sensor2;
|
|
tpoint->t1 = WeightedAverage(s1->min, s2->min, tpoint);
|
|
tpoint->t2 = WeightedAverage(s1->max, s2->max, tpoint);
|
|
if (fabsf(tpoint->t1 - tpoint->temp) < fabsf(tpoint->t2 - tpoint->temp)) {
|
|
tbuf = tpoint->t1;
|
|
tpoint->t1 = tpoint->t2;
|
|
tpoint->t2 = tbuf;
|
|
}
|
|
s1->min=0;
|
|
s1->max=0;
|
|
s2->min=0;
|
|
s2->max=0;
|
|
}
|
|
|
|
if (cryo.t1!=DATA_UNDEF) {
|
|
sprintf(buf1, " Tm %.5g _ %.5g", cryo.t1, cryo.t2);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (cryo.sensor1!=samp.sensor1 && samp.t1!=DATA_UNDEF) {
|
|
sprintf(buf1, " Ts %.5g _ %.5g", samp.t1, samp.t2);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (tr!=DATA_UNDEF) {
|
|
sprintf(buf1, " Tr %.5g", tr);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (te!=DATA_UNDEF) {
|
|
sprintf(buf1, " Te %.5g", te);
|
|
str_append(buf, buf1);
|
|
}
|
|
} else if (nScan==0) {
|
|
return;
|
|
}
|
|
for (i=4; i<4+nScan; i++) {
|
|
s1=sensors[i];
|
|
if (s1->t!=DATA_UNDEF) {
|
|
sprintf(buf1, " T%c %.5g", s1->ch[1], s1->t);
|
|
str_append(buf, buf1);
|
|
}
|
|
}
|
|
if (power!=DATA_UNDEF) {
|
|
sprintf(buf1, " P %.4g", power);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (he!=DATA_UNDEF) {
|
|
sprintf(buf1, " He %.4g", he);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (aux!=DATA_UNDEF) {
|
|
sprintf(buf1, " Aux %.5g", aux);
|
|
str_append(buf, buf1);
|
|
}
|
|
if (new==2) {
|
|
mmTime=mmTime+30;
|
|
first=1;
|
|
} else {
|
|
if (first==0) {
|
|
logfileOut(LOG_MAIN, "%s\n", buf);
|
|
} else {
|
|
first=0;
|
|
}
|
|
if (new) {
|
|
mmInt=30;
|
|
} else {
|
|
mmInt=60;
|
|
}
|
|
mmTime=((tim+mmInt/2)/mmInt+1)*mmInt-logPeriod;
|
|
}
|
|
}
|
|
|
|
float CtlScale(void) {
|
|
if (controlMode==1) {
|
|
tShift=0;
|
|
if (ctlSens==NULL) {
|
|
ctlSens=samp.sensor1;
|
|
} else if (ctlSens==samp.sensor1) {
|
|
if (set < ctlSens->lim) {
|
|
ctlSens=samp.sensor2;
|
|
}
|
|
} else if (ctlSens==samp.sensor2) {
|
|
if (set > ctlSens->lim) {
|
|
ctlSens=samp.sensor1;
|
|
}
|
|
} else {
|
|
ctlSens=samp.sensor1;
|
|
}
|
|
} else {
|
|
if (controlMode!=2) tShift=0;
|
|
if (ctlSens==NULL) {
|
|
ctlSens=cryo.sensor1;
|
|
} else if (ctlSens==cryo.sensor1) {
|
|
if (set < ctlSens->lim) {
|
|
ctlSens=cryo.sensor2;
|
|
}
|
|
} else if (ctlSens==cryo.sensor2) {
|
|
if (set > ctlSens->lim) {
|
|
ctlSens=cryo.sensor1;
|
|
}
|
|
} else {
|
|
ctlSens=cryo.sensor1;
|
|
}
|
|
}
|
|
if (ctlSens==NULL) {
|
|
return 1.0;
|
|
} else {
|
|
return ctlSens->scale;
|
|
}
|
|
}
|
|
|
|
int ReadTemp(void) {
|
|
char buf[256], typ, *err;
|
|
int i, doit, stat;
|
|
int tfill, dfill;
|
|
static int iScan=0;
|
|
float hlev;
|
|
SensorT *s;
|
|
|
|
readTemp=0;
|
|
|
|
doit=0;
|
|
if (nScan>0) {
|
|
while (1) { /* read until a non-selected channel found */
|
|
if (iScan>=nScan) iScan=0;
|
|
s=sensors[iScan+4];
|
|
if (s->present<1) break;
|
|
str_copy(chan, s->ch);
|
|
ERR_P(LscCmd(ser, "KRDG?[chan]>fbuf;DIOST?>,out1"));
|
|
if (out1==iScan) break;
|
|
s->t=fbuf;
|
|
iScan++;
|
|
}
|
|
}
|
|
for (i=0; i<4; i++) {
|
|
s=sensors[i];
|
|
s->stat1=0;
|
|
s->stat2=0;
|
|
if (s->present) {
|
|
if (doit) ERR_P(LscCmd(ser, buf));
|
|
if (i<4) {
|
|
str_substitute(buf
|
|
, "KRDG?#>sens#.t0;MDAT?#>sens#.t1,sens#.t2;MDATST?#>sens#.stat1,sens#.stat2"
|
|
, "#", s->ch);
|
|
} else {
|
|
str_substitute(buf
|
|
, "KRDG?#>sens#.t1;RDGST?#>sens#.stat1;DIOST?>,sens#.stat2"
|
|
, "#", s->ch);
|
|
}
|
|
if (s->type=='h' || s->type=='x') {
|
|
buf[0]='S'; /* change KRDG to SRDG */
|
|
typ='S';
|
|
} else if (s->type=='f') {
|
|
buf[0]='L'; /* change KRDG to LDAT */
|
|
buf[1]='D';
|
|
buf[2]='A';
|
|
buf[3]='T';
|
|
}
|
|
doit=1;
|
|
}
|
|
}
|
|
if (doit) {
|
|
if (ramp!=0) {
|
|
str_append(buf, ";SETP?[loop]>fbuf");
|
|
}
|
|
str_append(buf, ";MNMXRST");
|
|
ERR_P(LscCmd(ser, buf));
|
|
if (ramp!=0) {
|
|
tr=fbuf*CtlScale();
|
|
} else {
|
|
tr=setH*CtlScale();
|
|
}
|
|
if (tr==0) tr=DATA_UNDEF;
|
|
}
|
|
|
|
/* check for reading errors, determine legal value */
|
|
for (i=0; i<4; i++) {
|
|
s=sensors[i];
|
|
if (s->present) {
|
|
|
|
if (i>=4) {
|
|
if (s->stat2==i-4) { /* ignore reading, if channel was active (may be noisy) */
|
|
s->t1 = s->t;
|
|
}
|
|
s->t2 = s->t1;
|
|
s->stat2 = s->stat1;
|
|
}
|
|
if (s->t1 == 63.0 || s->t2 == 63.0 || s->t0 == 63.0) {
|
|
/* probably noisy values */
|
|
logfileOut(LOG_MAIN, "magic %s: %g %g %g\n", s->ch, s->t1, s->t2, s->t0);
|
|
}
|
|
|
|
stat=(s->stat1 & s->stat2) & (255-3); /* ignore "old reading" and "invalid reading", error must be on min & max */
|
|
if (stat > s->readStat || stat==0 && s->readStat>0) {
|
|
err=LscReadStat(stat);
|
|
if (*err=='\0') {
|
|
logfileOut(LOG_MAIN, "reading o.k. %s\n", s->ch);
|
|
} else {
|
|
logfileOut(LOG_MAIN, "%s %s\n", err, s->ch);
|
|
}
|
|
s->readStat=stat;
|
|
}
|
|
if (stat==0) {
|
|
|
|
if (s->type=='h') {
|
|
hlev = s->t1; /* take minimum only */
|
|
if (full>0) {
|
|
if (hlev<full && hlev>0) {
|
|
he=hlev*100.0/full;
|
|
s->t=he;
|
|
tfill = tim % (24*3600) / 60; /* min since midnight */
|
|
dfill = mycDate(tim) % 10000; /* fill date without year */
|
|
sprintf(helium, "%.3g %s (%02d.%02d., %02d:%02d)", he, heUnits
|
|
, dfill % 100, dfill / 100, tfill / 60, tfill % 60);
|
|
}
|
|
}
|
|
} else if (s->t2 - s->t1 <= s->band*2) { /* normal case */
|
|
s->t = (s->t1 + s->t2) * 0.5; /* mean of min and max */
|
|
s->band = s->band/2;
|
|
} else {
|
|
if (s->t1 < 0.8 * s->t2) {
|
|
/* probably noisy values */
|
|
logfileOut(LOG_MAIN, "min/max %s: %g %g\n", s->ch, s->t1, s->t2);
|
|
}
|
|
s->t=s->t0;
|
|
s->t1 = s->t;
|
|
s->t2 = s->t;
|
|
}
|
|
if (s->t1 < s->min || s->min==0.0) s->min = s->t1;
|
|
if (s->t2 > s->max) s->max = s->t2;
|
|
if (s->max - s->min > s->band) {
|
|
s->band = s->max - s->min;
|
|
}
|
|
} else {
|
|
s->t=DATA_UNDEF;
|
|
}
|
|
} else {
|
|
s->t=DATA_UNDEF;
|
|
}
|
|
}
|
|
|
|
rdTim=mycNow();
|
|
|
|
tm=DATA_UNDEF;
|
|
ts=DATA_UNDEF;
|
|
if (cryo.sensor1!=NULL) {
|
|
cryo.temp=WeightedAverage(cryo.sensor1->t, cryo.sensor2->t, &cryo);
|
|
samp.temp=WeightedAverage(samp.sensor1->t, samp.sensor2->t, &samp);
|
|
tm=cryo.temp;
|
|
if (samp.sensor1!=cryo.sensor1) {
|
|
ts=samp.temp;
|
|
}
|
|
if (samp.temp==DATA_UNDEF) {
|
|
samp.temp=cryo.temp;
|
|
}
|
|
} else if (nScan==0) {
|
|
tm=(rdTim % 3600) * 1.0e-4;
|
|
ts=(rdTim % 60) * 60.0e-4+0.5;
|
|
}
|
|
if (auxSens != NULL) {
|
|
aux=auxSens->t * auxSens->scale;
|
|
} else {
|
|
aux=DATA_UNDEF;
|
|
}
|
|
if (testSens != NULL) {
|
|
te=testSens->t * testSens->scale;
|
|
} else {
|
|
te=DATA_UNDEF;
|
|
}
|
|
if (heliumSens == NULL) {
|
|
he=DATA_UNDEF;
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int ReadHeater(void) {
|
|
if (loop==1) {
|
|
if (relay) {
|
|
ERR_P(LscCmd(ser, "HTRST?>htrst"));
|
|
htr=0;
|
|
} else {
|
|
ERR_P(LscCmd(ser, "HTR?>htr;HTRST?>htrst;RELAYST?1>relay"));
|
|
}
|
|
} else {
|
|
ERR_P(LscCmd(ser, "AOUT?2>htr"));
|
|
htrst=0;
|
|
}
|
|
if (set == 0) {
|
|
power=DATA_UNDEF;
|
|
} else {
|
|
power=htr*htr*scalPower*1e-4;
|
|
if (power>maxPower) power=maxPower;
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int SetTemp(int switchOn) {
|
|
int showSet;
|
|
float scale;
|
|
|
|
if (set<0 || set>tLimit) {
|
|
set=0;
|
|
logfileOut(LOG_MAIN, "set point not within (0 ... %g), reset to 0\n", tLimit);
|
|
}
|
|
if (switchOn) {
|
|
ERR_I(ReadTemp());
|
|
LogMinMax(switchOn);
|
|
}
|
|
scale=CtlScale();
|
|
if (ctlSens==NULL) return 0;
|
|
|
|
str_copy(chan, ctlSens->ch);
|
|
if (tShift>maxShift) {
|
|
tShift=maxShift;
|
|
} else if (tShift<-maxShift) {
|
|
tShift=-maxShift;
|
|
}
|
|
setH=(set+tShift)/scale;
|
|
if (setH>tLimit/scale) setH=tLimit/scale;
|
|
if (switchOn) {
|
|
/* switch off other loop */
|
|
if (loop==1) {
|
|
ERR_P(LscCmd(ser, "CSET 2:[chan],1,0,0"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "CSET 1:[chan],1,0,0"));
|
|
}
|
|
if (ramp > 0 && set != 0) {
|
|
/* take ramp from actual temperature if more than 1 % deviation */
|
|
ERR_P(LscCmd(ser, "CSET?[loop]>,,cod1;SETP?[loop]>fbuf"));
|
|
tr=fbuf*scale;
|
|
if (cod1 == 0 || fabsf(ctlSens->t - tr) >= 0.1 * ctlSens->t) {
|
|
fbuf = ctlSens->t;
|
|
tr = fbuf * scale;
|
|
ERR_P(LscCmd(ser, "SETP [loop],[fbuf];RAMP [loop],0,0;SETP [loop],[fbuf]"));
|
|
}
|
|
}
|
|
}
|
|
if (set==0) {
|
|
ERR_P(LscCmd(ser, "CSET [loop]:[chan],1,1,0"));
|
|
if (loop==1) {
|
|
ERR_P(LscCmd(ser, "RANGE:0"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "ANALOG 2:0,0"));
|
|
}
|
|
setH=0;
|
|
} else if (switchOn) { /* switch on also when bad heater message and no alarms: || (htrst>=5 && !relay)) */
|
|
ERR_P(LscCmd(ser, "CSET [loop]:[chan],1,1,0"));
|
|
if (loop==1) {
|
|
ERR_P(LscCmd(ser, "RANGE:[iRange]"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "ANALOG 2:0,3"));
|
|
}
|
|
} else {
|
|
ERR_P(LscCmd(ser, "CSET?[loop]>,buf1,"));
|
|
if (buf1[0] != '1') {
|
|
ERR_P(LscCmd(ser, "CSET [loop]:[chan],1"));
|
|
}
|
|
}
|
|
showSet=(0!=strcmp(ctlSens->ch, controlChannel) || switchOn);
|
|
str_copy(controlChannel, ctlSens->ch);
|
|
if (ramp==0 || set==0) {
|
|
ERR_P(LscCmd(ser, "RAMP?[loop]>buf1,"));
|
|
if (buf1[0] != '0') {
|
|
ERR_P(LscCmd(ser, "RAMP [loop]:0,[ramp]"));
|
|
}
|
|
ERR_P(LscCmd(ser, "SETP?[loop]>fbuf"));
|
|
if (fabsf(setH-fbuf) >= (fbuf+setH)*1.0e-5) {
|
|
ERR_P(LscCmd(ser, "SETP [loop]:[setH]"));
|
|
if (controlMode!=2 && !showSet) {
|
|
logfileOut(LOG_MAIN, "set %g (on %s) (was changed %g -> %g)\n", set, ctlSens->ch, fbuf, setH);
|
|
}
|
|
} else {
|
|
setH=fbuf;
|
|
}
|
|
tr=setH*scale;
|
|
if (showSet) {
|
|
logfileOut(LOG_MAIN, "set %g (on %s)\n", set, ctlSens->ch);
|
|
}
|
|
} else {
|
|
if (ramp < 0) ramp=-ramp;
|
|
if (ramp < 0.1) ramp=0.1;
|
|
if (showSet) {
|
|
ERR_P(LscCmd(ser, "RAMP [loop]:1,[ramp];SETP [loop],[setH];SETP?[loop]>fbuf"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "SETP?[loop]>fbuf"));
|
|
if (fabs(fbuf-setH) >= ramp*smooth) {
|
|
fbuf=ramp;
|
|
} else {
|
|
fbuf=sqrt(fabs(fbuf-setH)*ramp/smooth);
|
|
if (fbuf<0.1) fbuf=0.1;
|
|
}
|
|
ERR_P(LscCmd(ser, "RAMP [loop]:1,[fbuf];SETP [loop],[setH]"));
|
|
ERR_P(LscCmd(ser, "SETP?[loop]>fbuf"));
|
|
}
|
|
tr=fbuf*scale;
|
|
if (showSet) {
|
|
logfileOut(LOG_MAIN, "set %g (on %s) %g K/min, starting from %g\n", set, ctlSens->ch, ramp, tr);
|
|
}
|
|
}
|
|
if (tr==0) tr=DATA_UNDEF;
|
|
if (showSet) {
|
|
/* relay=0; */
|
|
ERR_I(ReadHeater());
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
void CalcMaxPower(void) {
|
|
int i, j, vmax;
|
|
float pa, pr, pw, quo, p, pl, plim;
|
|
|
|
iAmp=1; iRange=0;
|
|
if (scalPower==0) scalPower=maxPower;
|
|
if (maxPower>0) {
|
|
p=scalPower/powFact;
|
|
plim=2500/resist;
|
|
/* power limited by 50 V output. U*U/R=2500/R */
|
|
if (p>plim) p=plim;
|
|
pa=resist*4; /* max. maxPower R*I*I (I=2 A) */
|
|
pw=0; quo=0.;
|
|
for (i=4; i>0; i--) {
|
|
pr=pa;
|
|
for (j=5; j>0; j--) {
|
|
if (p<pr) {
|
|
if (p/pr>quo) { quo=p/pr; pw=pr; iAmp=i; iRange=j; }
|
|
} else if (p<plim || pw==0) {
|
|
if (pr/p>quo) { quo=pr/p; pw=pr; iAmp=i; iRange=j; }
|
|
}
|
|
pr=pr/10;
|
|
}
|
|
pa=pa/4;
|
|
}
|
|
scalPower=pw*powFact;
|
|
assert(scalPower>0);
|
|
if (scalPower<plim*powFact) {
|
|
maxPower=scalPower;
|
|
} else {
|
|
maxPower=plim*powFact;
|
|
}
|
|
} else {
|
|
iRange=0;
|
|
}
|
|
}
|
|
|
|
int SetMaxPower(void) {
|
|
static float p0, pold;
|
|
float plim;
|
|
|
|
if (loop == 1) {
|
|
ERR_P(LscCmd(ser, "CLIMIT?1>,,,iAmp,iRange"));
|
|
if (iRange>0) {
|
|
p0=resist*pow(4.0,iAmp)*pow(10.0,iRange)/6.4e6*powFact;
|
|
plim=2500/resist;
|
|
pold=p0;
|
|
if (pold>plim) pold=plim;
|
|
}
|
|
CalcMaxPower();
|
|
}
|
|
logfileOut(LOG_MAIN, "maxPower changed from %g to %g\n", pold, maxPower);
|
|
ERR_P(LscCmd(ser, "CDISP 1:[loop],[resist],1;MOUT [loop]:0;CMODE [loop]:1"));
|
|
if (slope<0) slope=-slope;
|
|
if (slope!=0 && slope<0.1) slope=0.1;
|
|
fbuf=tLimit/CtlScale();
|
|
if (loop==1) {
|
|
if (scalPower!=0) prop=sqrt(p0/scalPower)*prop;
|
|
ERR_P(LscCmd(ser, "CLIMIT 1:[fbuf],[slope],0,[iAmp],[iRange];PID [loop],[prop]"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "CLIMIT 2:[fbuf],[slope],0"));
|
|
}
|
|
p0=scalPower;
|
|
pold=maxPower;
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
char DisplayFmt(SensorT *s) {
|
|
if (s==NULL || s->present<=0 || s->type=='h') return '\0';
|
|
if (s->type=='x') {
|
|
return '3';
|
|
} else if (s->type=='f') {
|
|
return '4';
|
|
} else {
|
|
if (s->scale==1.0) {
|
|
return '1';
|
|
} else {
|
|
return '4';
|
|
}
|
|
}
|
|
}
|
|
|
|
int ConfigAlarms(void) {
|
|
int i, k;
|
|
SensorT *s;
|
|
|
|
ERR_P(LscCmd(ser, "RELAY 1:1;BEEP:0"));
|
|
relay=0;
|
|
k=0;
|
|
for (i=0;i<4+nScan;i++) {
|
|
s=sensors[i];
|
|
str_copy(buf1, s->ch);
|
|
if (s->present==1 && s->alarm>0) {
|
|
r1=s->alarm/s->scale;
|
|
ERR_P(LscCmd(ser, "ALARM [buf1]:1,1,[r1],0,1,1"));
|
|
alarmList[k]=s->ch;
|
|
k++;
|
|
} else {
|
|
ERR_P(LscCmd(ser, "ALARM [buf1]:0")); /* switch off unused alarms */
|
|
}
|
|
}
|
|
alarmListSize=k;
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int LoadFromLsc(void) {
|
|
ERR_P(LscCmd(ser, "PID?[loop]>prop,integ,deriv"));
|
|
ERR_P(LscCmd(ser, "RAMP?[loop]>,ramp"));
|
|
ERR_P(LscCmd(ser, "ANALOG?1>,,,,,,fbuf"));
|
|
still=fbuf*fbuf/70;
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int Settings(void) {
|
|
char buf[256], typ;
|
|
char *flds[6], fmt[6];
|
|
char *cfg, *p;
|
|
int i,k,l;
|
|
SensorT *s;
|
|
|
|
if (remoteMode!=2) {
|
|
remoteMode=2; /* set to remote mode */
|
|
ERR_I(LoadFromLsc());
|
|
ERR_P(LscCmd(ser, "MODE:[remoteMode]"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "PID [loop],[prop],[integ],[deriv]"));
|
|
}
|
|
for (i=0; i<4+nScan; i++) {
|
|
s=sensors[i];
|
|
if (i<4) {
|
|
plug=plugs[i/2];
|
|
} else {
|
|
plug=&plug0;
|
|
}
|
|
if (s->present < 0) {
|
|
if (settingsFlag) return 0;
|
|
if (i==4) {
|
|
ERR_P(LscCmd(ser, "DOUT:2;XSCAN:2,,2"));
|
|
}
|
|
ERR_I(InstalCurve(s, plug->device));
|
|
}
|
|
}
|
|
if (nScan>0) {
|
|
for (out1=nScan+1;out1<=4;out1++) {
|
|
ERR_P(LscCmd(ser, "INSET A[out1],0"));
|
|
}
|
|
ERR_P(LscCmd(ser, "INSET A5,0;INSET A6,0;INSET A7,0;INSET A8,0"));
|
|
ERR_P(LscCmd(ser, "INSET A9,0;INSET A10,0;INSET A11,0;INSET A12,0"));
|
|
ERR_P(LscCmd(ser, "INSET A13,0;INSET A14,0;INSET A15,0;INSET A16,0"));
|
|
}
|
|
|
|
cryo.sensor1=NULL;
|
|
cryo.sensor2=NULL;
|
|
samp.sensor1=NULL;
|
|
samp.sensor2=NULL;
|
|
heliumSens=NULL;
|
|
auxSens=NULL;
|
|
testSens=NULL;
|
|
for (i=0; i<4+nScan; i++) {
|
|
s=sensors[i];
|
|
if (s->present==1) {
|
|
typ=s->type;
|
|
if ('m'==typ) {
|
|
if (cryo.sensor2==NULL) cryo.sensor2=s;
|
|
cryo.sensor1=s;
|
|
} else if ('n'==typ) {
|
|
if (cryo.sensor1==NULL) cryo.sensor1=s;
|
|
cryo.sensor2=s;
|
|
} else if ('s'==typ) {
|
|
if (samp.sensor2==NULL) samp.sensor2=s;
|
|
samp.sensor1=s;
|
|
} else if ('l'==typ) {
|
|
if (samp.sensor1==NULL) samp.sensor1=s;
|
|
samp.sensor2=s;
|
|
} else if ('h'==typ) {
|
|
heliumSens=s;
|
|
} else if ('x'==typ || 'f'==typ) {
|
|
auxSens=s;
|
|
} else if ('t'==typ) {
|
|
testSens=s;
|
|
}
|
|
s->band=10;
|
|
}
|
|
}
|
|
if (cryo.sensor1==NULL) {
|
|
cryo.sensor1=samp.sensor1;
|
|
cryo.sensor2=samp.sensor2;
|
|
} else if (samp.sensor1==NULL) {
|
|
samp.sensor1=cryo.sensor1;
|
|
samp.sensor2=cryo.sensor2;
|
|
}
|
|
|
|
if (settingsFlag) return 0;
|
|
|
|
s=cryo.sensor1;
|
|
if (s!=NULL) {
|
|
ERR_I(SetMaxPower());
|
|
}
|
|
|
|
if (settingsFlag) return 0;
|
|
|
|
str_copy(statusBuf, "alarms");
|
|
ERR_I(ConfigAlarms());
|
|
|
|
if (settingsFlag) return 0;
|
|
|
|
str_copy(statusBuf, "display");
|
|
|
|
/* display */
|
|
k=1;
|
|
|
|
fmt[k]=DisplayFmt(cryo.sensor1);
|
|
if (fmt[k]!='\0') {
|
|
flds[k]=cryo.sensor1->ch;
|
|
k++;
|
|
}
|
|
if (samp.sensor1 != cryo.sensor1) {
|
|
fmt[k]=DisplayFmt(samp.sensor1);
|
|
if (fmt[k]!='\0') {
|
|
flds[k]=samp.sensor1->ch;
|
|
k++;
|
|
}
|
|
}
|
|
if (cryo.sensor2 != cryo.sensor1) {
|
|
fmt[k]=DisplayFmt(cryo.sensor2);
|
|
if (fmt[k]!='\0') {
|
|
flds[k]=cryo.sensor2->ch;
|
|
k++;
|
|
}
|
|
}
|
|
if (samp.sensor2 != samp.sensor1 && samp.sensor2 != cryo.sensor2) {
|
|
fmt[k]=DisplayFmt(samp.sensor2);
|
|
if (fmt[k]!='\0') {
|
|
flds[k]=samp.sensor2->ch;
|
|
k++;
|
|
}
|
|
}
|
|
fmt[k]=DisplayFmt(testSens);
|
|
if (fmt[k]!='\0' && k<=4) {
|
|
flds[k]=testSens->ch;
|
|
k++;
|
|
}
|
|
fmt[k]=DisplayFmt(auxSens);
|
|
if (fmt[k]!='\0' && k<=4) {
|
|
flds[k]=auxSens->ch;
|
|
k++;
|
|
}
|
|
if (nScan>0) {
|
|
i=0;
|
|
while (k<=4 && i<nScan) {
|
|
fmt[k]=DisplayFmt(sensors[i+4]);
|
|
if (fmt[k]!='\0') {
|
|
flds[k]=sensors[i+4]->ch;
|
|
k++; i++;
|
|
}
|
|
}
|
|
}
|
|
maxfld=k-1;
|
|
|
|
/* 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++) {
|
|
assert(l<128);
|
|
sprintf(buf+l, "DISPFLD %d,%s,%c;", k, flds[k], fmt[k]);
|
|
l=strlen(buf);
|
|
}
|
|
str_append(buf, "DISPLAY:[maxfld]");
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
if (config[0] != '\0') {
|
|
str_copy(buf, binDir);
|
|
str_append(buf, config);
|
|
cfg=str_read_file(buf);
|
|
if (cfg != NULL) {
|
|
logfileOut(LOG_MAIN, "load %s\n", config);
|
|
p=cfg;
|
|
while (p!=NULL) {
|
|
p=str_split(buf, p, '\n');
|
|
ERR_P(LscCmd(ser, buf));
|
|
}
|
|
FREE(cfg);
|
|
}
|
|
}
|
|
|
|
if (settingsFlag) return 0;
|
|
str_copy(statusBuf, "reading temperatures");
|
|
|
|
if (cryo.sensor1!=NULL) {
|
|
ERR_I(SetTemp(2));
|
|
} else {
|
|
ERR_I(ReadTemp());
|
|
}
|
|
logTime=(rdTim / logPeriod + 2) * logPeriod; /* wait before logging "dirty" temperatures */
|
|
return 0;
|
|
OnError:
|
|
return -1;
|
|
}
|
|
|
|
int ConfigByCode(int plugNr) {
|
|
char buf[16];
|
|
|
|
plug=plugs[plugNr];
|
|
str_copy(plug->device,"");
|
|
plug->manual=0;
|
|
ConcatDevice();
|
|
if (plug->code==0) {
|
|
logfileOut(LOG_MAIN ,"reset inputs on plug%d\n", plugNr);
|
|
plug->sensor1->present=0;
|
|
plug->sensor2->present=0;
|
|
} else {
|
|
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for cod %+d\n", plugNr, plug->code);
|
|
sprintf(buf, "%+d,", plug->code);
|
|
ERR_I(PrepInput(buf));
|
|
}
|
|
settingsFlag=1;
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int ConfigByName(int plugNr) {
|
|
char buf[20];
|
|
|
|
plug=plugs[plugNr];
|
|
plug->manual=1;
|
|
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for %s\n", plugNr, plug->device);
|
|
plug->sensor1->present=0;
|
|
plug->sensor2->present=0;
|
|
if (0!=strcmp(plug->device, "none")) {
|
|
sprintf(buf, "'%s'", plug->device);
|
|
ERR_I(PrepInput(buf));
|
|
}
|
|
settingsFlag=1;
|
|
return 0;
|
|
OnError:
|
|
plug->device[0]='\0';
|
|
ConcatDevice();
|
|
return -1;
|
|
}
|
|
|
|
int PeriodicTask(void) {
|
|
char buf[256], lbuf[16];
|
|
char *next, *alms;
|
|
int i, k;
|
|
float t3[3], p, d, w, t;
|
|
|
|
if (nScan==0) {
|
|
ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;BUSY?>busy"));
|
|
} else {
|
|
cod1=0;
|
|
ERR_P(LscCmd(ser, "BUSY?>busy"));
|
|
}
|
|
if (plug0.codDefined && plug1.codDefined || nScan>0) {
|
|
per=period; /* no timeout on above command and codes are defined: normal period */
|
|
if (per>logPeriod*1000) per=logPeriod*1000;
|
|
}
|
|
if (noResp) { /* there was no response on an earlier command, or we are initializing */
|
|
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 (k!=0) {
|
|
logfileOut(LOG_MAIN, "controller connected\n");
|
|
}
|
|
set=0;
|
|
|
|
/* 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());
|
|
|
|
/* get device names and last codes separated by '/' */
|
|
str_split(buf, cache, '\n'); /* read 1 line */
|
|
plug1.device[0]='\0';
|
|
plug0.code=0;
|
|
plug1.code=0;
|
|
next=str_split(buf1, buf, '/');
|
|
if (next!=NULL) {
|
|
next=str_split(buf2, next, '/');
|
|
if (next!=NULL) {
|
|
next=str_split(buf3, next, '/');
|
|
plug0.code=atoi(buf3);
|
|
plug0.codChanged=1;
|
|
if (next!=NULL) {
|
|
next=str_split(buf3, next, '\n');
|
|
plug1.code=atoi(buf3);
|
|
plug1.codChanged=1;
|
|
}
|
|
}
|
|
}
|
|
if (buf1[0]=='*') {
|
|
str_copy(plug0.device, buf1+1);
|
|
plug0.codChanged=0;
|
|
ConfigByName(0);
|
|
} else {
|
|
if (plug0.code!=0) str_copy(plug0.device, buf1);
|
|
plug0.manual=0;
|
|
}
|
|
if (buf2[0]=='*') {
|
|
str_copy(plug1.device, buf2+1);
|
|
plug1.codChanged=0;
|
|
ConfigByName(1);
|
|
} else {
|
|
if (plug1.code!=0) str_copy(plug1.device, buf2);
|
|
plug1.manual=0;
|
|
}
|
|
ConcatDevice();
|
|
|
|
settingsFlag=1;
|
|
}
|
|
noResp=0;
|
|
}
|
|
|
|
ERR_I(ReadHeater());
|
|
|
|
if (relay || loop !=1) {
|
|
if (alarmListSize!=0) {
|
|
buf[0]='\0';
|
|
for (k=0;k<alarmListSize;k++) {
|
|
str_append(buf,";ALARMST?");
|
|
str_append(buf, alarmList[k]);
|
|
}
|
|
ERR_P(alms=LscCmd(ser, buf+1)); /* send without leading semicolon */
|
|
if (0!=strcmp(alarmStatus, alms)) {
|
|
str_copy(alarmStatus, alms);
|
|
alarmChannels[0]='\0';
|
|
for (k=0;k<alarmListSize;k++) {
|
|
if (alms[k*4] != '0' || alms[k*4+2] != '0') {
|
|
str_append(alarmChannels, alarmList[k]);
|
|
str_append(alarmChannels, " ");
|
|
if (NULL==strstr(alarmHistory, alarmList[k])) { /* if not yet in history */
|
|
str_append(alarmHistory, alarmList[k]); /* add to history */
|
|
}
|
|
}
|
|
}
|
|
if (alarmChannels[0]=='\0') {
|
|
if (lockAlarm) {
|
|
logfileOut(LOG_MAIN, "No more active alarms, latching alarms: %s!\n", alarmHistory);
|
|
} else {
|
|
alarmHistory[0]='\0';
|
|
alarmChannels[0]='\0';
|
|
logfileOut(LOG_MAIN, "No more active alarms\n");
|
|
ERR_P(LscCmd(ser, "ALMRST"));
|
|
relay=0;
|
|
}
|
|
} else {
|
|
logfileOut(LOG_MAIN, "Alarm on channel %s\n", alarmChannels);
|
|
if (!relay0 && set!=0) {
|
|
lockAlarm=1;
|
|
logfileOut(LOG_MAIN, "Switch off heater\n");
|
|
if (loop==1) { /* turn on high relay manually, switch off heater and reset alarms */
|
|
ERR_P(LscCmd(ser, "RELAY 1:2,1;RANGE:0;ALMRST"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "RELAY 1:2,1;ANALOG 2:0,0;ALMRST"));
|
|
relay=1;
|
|
}
|
|
} else {
|
|
ERR_P(LscCmd(ser, "ALMRST"));
|
|
}
|
|
}
|
|
} else {
|
|
ERR_P(LscCmd(ser, "ALMRST"));
|
|
}
|
|
} else if (loop == 1) {
|
|
if (!relay0) logfileOut(LOG_MAIN, "Relay is on!\n");
|
|
alarmStatus[0]='\0';
|
|
}
|
|
} else if (loop == 1) {
|
|
alarmChannels[0]='\0';
|
|
alarmStatus[0]='\0';
|
|
}
|
|
relay0=relay;
|
|
|
|
ERR_I(ReadTemp());
|
|
|
|
if (htrst!=htrst0) {
|
|
LogMinMax(0);
|
|
if (htrst==0) {
|
|
logfileOut(LOG_MAIN, "heater o.k.\n");
|
|
} else {
|
|
logfileOut(LOG_MAIN, "%s\n", LscHtrStat(htrst));
|
|
}
|
|
htrst0=htrst;
|
|
}
|
|
|
|
if (rdTim>=logTime) {
|
|
ERR_I(DataPutAll(NULL, rdTim));
|
|
logTime=(rdTim / logPeriod + 1) * logPeriod;
|
|
if (rdTim>mmTime && (cryo.sensor1 != NULL || nScan>0)) LogMinMax(0);
|
|
}
|
|
if (set!=0 && remoteMode==2) {
|
|
if (cryo.sensor1!=samp.sensor1 && controlMode==2) {
|
|
t=ctlSens->t;
|
|
d=(setH-t)/t; /* 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) tInt+=w*per/1000; /* 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));
|
|
} else {
|
|
ERR_I(SetTemp(0));
|
|
}
|
|
}
|
|
|
|
if (nScan==0) {
|
|
ERR_P(LscCmd(ser, "KEYST?>key;DIOST?>cod2,out2;DOUT 3,30"));
|
|
} else {
|
|
ERR_P(LscCmd(ser, "KEYST?>key"));
|
|
}
|
|
if (busy==0) {
|
|
if (nScan==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 */
|
|
plug0.code1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */
|
|
plug1.code1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]);
|
|
for (i=0; i<2; i++) {
|
|
plug=plugs[i];
|
|
if (plug->code1!=plug->code) { /* code has changed -> wait for a confirmation */
|
|
if (plug->code1!=plug->code2) {
|
|
plug->code2=plug->code1;
|
|
} else {
|
|
plug->code=plug->code1;
|
|
plug->codChanged=1;
|
|
}
|
|
} else {
|
|
plug->code2=plug->code;
|
|
if (plug->codChanged) { /* code change confirmed */
|
|
plug->codChanged=0;
|
|
if (plug->code1==0) {
|
|
logfileOut(LOG_MAIN, "plug%d unplugged\n", i);
|
|
} else {
|
|
logfileOut(LOG_MAIN, "plugged %d on plug%d\n", plug->code1, i);
|
|
}
|
|
set=0;
|
|
ERR_I(ConfigByCode(i));
|
|
}
|
|
plug->codDefined=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (key!=0) {
|
|
ERR_P(LscCmd(ser, "MODE?>remoteMode"));
|
|
if (!touched) {
|
|
touched=1;
|
|
logfileOut(LOG_MAIN ,"user touched keys\n");
|
|
}
|
|
if (remoteMode==2) {
|
|
logfileOut(LOG_MAIN ,"user switched to remote\n");
|
|
touched=0;
|
|
ERR_I(LoadFromLsc());
|
|
if (controlMode==2) {
|
|
ERR_P(LscCmd(ser, "RANGE?>iRange"));
|
|
if (iRange==0) set=0;
|
|
} else {
|
|
ERR_P(LscCmd(ser, "RAMP?[loop]>,ramp"));
|
|
ERR_P(LscCmd(ser, "RANGE?>iRange;CSET?[loop]>,cod1,;SETP?[loop]>set"));
|
|
if (cod1!=1) {
|
|
set=0;
|
|
logfileOut(LOG_MAIN, "set point was not in K, set to 0\n");
|
|
}
|
|
}
|
|
settingsFlag=1;
|
|
}
|
|
}
|
|
|
|
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 DeviceHdl(int mode, void *base, int fd) {
|
|
char *t, *res;
|
|
int do0, do1;
|
|
|
|
if (mode==COC_WR) {
|
|
set=0;
|
|
t=strchr(device, '/');
|
|
if (t==NULL) {
|
|
if (0==strcmp(device, "0") || 0==strcasecmp(device, "auto")) {
|
|
nScan=0;
|
|
ERR_I(ConfigByCode(0));
|
|
ERR_I(ConfigByCode(1));
|
|
} else {
|
|
str_copy(plug0.device, device);
|
|
str_copy(plug1.device, device);
|
|
ERR_I(ConfigByName(0));
|
|
ERR_I(ConfigByName(1));
|
|
}
|
|
} else {
|
|
do0=0;
|
|
do1=0;
|
|
if (t!=device) {
|
|
*t='\0';
|
|
str_copy(plug0.device, device);
|
|
*t='/';
|
|
do0=1;
|
|
}
|
|
t++;
|
|
if (*t!='\0') {
|
|
str_copy(plug1.device, t);
|
|
do1=1;
|
|
}
|
|
if (do0) ERR_I(ConfigByName(0));
|
|
if (do1) ERR_I(ConfigByName(1));
|
|
}
|
|
ConcatDevice();
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int SetHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
if (remoteMode!=2) {
|
|
ERR_MSG("controller is in local mode, enter 'remote' first");
|
|
} else if (relay && set!=0) {
|
|
if (alarmChannels[0]!='\0') {
|
|
ERR_MSG("alarm is active, set prohibited");
|
|
} else {
|
|
ERR_MSG("alarm was active, enter 'reset' first");
|
|
}
|
|
} else if (set<0) {
|
|
set=0;
|
|
} else if (set>tLimit) {
|
|
set=0;
|
|
ERR_MSG("set point too high");
|
|
}
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
if (cryo.sensor1!=NULL && remoteMode==2) {
|
|
tInt=0; /* reset integral time */
|
|
ERR_I(SetTemp(1));
|
|
}
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int PidHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
ERR_P(LscCmd(ser,"PID [loop]:[prop],[integ],[deriv]"));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int AlarmHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
ERR_I(ConfigAlarms());
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int MaxPowerHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
scalPower=maxPower;
|
|
CalcMaxPower();
|
|
if (remoteMode!=2) {
|
|
ERR_MSG("controller is in local mode, enter 'remote' first");
|
|
} else if (relay) {
|
|
if (alarmChannels[0]!='\0') {
|
|
ERR_MSG("alarm is active, maxPower prohibited");
|
|
} else {
|
|
ERR_MSG("alarm was active, enter 'reset' first");
|
|
}
|
|
}
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR && remoteMode==2) {
|
|
ERR_I(SetMaxPower());
|
|
ERR_I(SetTemp(1));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int StillHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
fbuf=sqrt(still*70);
|
|
ERR_P(LscCmd(ser,"ANALOG 1:0,2,,,,,[fbuf]"));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int SendHdl(int mode, void *base, int fd) {
|
|
char *res;
|
|
ClientData *data;
|
|
|
|
if (mode==COC_WR) {
|
|
return COC_DRD;
|
|
} else if (mode==COC_DRD) {
|
|
data=base;
|
|
if (NULL!=strchr(data->cmd, '>') || NULL!=strchr(data->cmd, '['))
|
|
ERR_MSG("no variables allowed");
|
|
ERR_P(res=LscCmd(ser, data->cmd));
|
|
str_copy(data->cmd, res);
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int LogHdl(int mode, void *base, int fd) {
|
|
ClientData *data;
|
|
|
|
if (mode==COC_RD) {
|
|
data=base;
|
|
if (data->logstart != 0) {
|
|
data->logpos = logfilePos(data->logstart);
|
|
data->logstart = 0;
|
|
}
|
|
data->logpos=logfileGetLines(data->logpos, 25, data->logline, sizeof(data->logline));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int PltHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_RD) {
|
|
ERR_MSG("Tecs client version not up to date");
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int GraHdl(int mode, void *base, int fd) {
|
|
ClientData *data;
|
|
int l;
|
|
char names[64];
|
|
long startTime, endTime, step;
|
|
|
|
if (mode==COC_RD) {
|
|
ERR_SI(sscanf(grapar, "%ld %ld %ld %n", &startTime, &endTime, &step, &l)-2);
|
|
str_copy(names, grapar+l);
|
|
ERR_I(l=DataGetMult(names, startTime, endTime, step, 30, gradata, sizeof(gradata)/sizeof(float)));
|
|
assert(l*sizeof(float)<sizeof(gradata));
|
|
*grasize=l;
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int PutFloat(StrBuf *buf, int prec, float f) {
|
|
char num[32], fmt[32];
|
|
int l;
|
|
|
|
if (f == DATA_UNDEF) {
|
|
return StrPut(buf, "NaN", StrNONE);
|
|
} else {
|
|
sprintf(fmt, "%%.%dg", prec);
|
|
sprintf(num, fmt, f);
|
|
return StrPut(buf, num, StrNONE);
|
|
}
|
|
}
|
|
|
|
int ShowSensor(StrBuf *buf, SensorT *s, char *name, char *units, char lim) {
|
|
|
|
if (s->present!=1) return 0;
|
|
ERR_I(StrPut(buf, "\n ", ' '));
|
|
ERR_I(StrPut(buf, s->ch, ':'));
|
|
ERR_I(StrPut(buf, "", ' '));
|
|
if (s->readStat==0) {
|
|
if (s->t==0) {
|
|
ERR_I(StrPut(buf, "not yet read", StrNONE));
|
|
} else {
|
|
ERR_I(StrPut(buf, name, '='));
|
|
ERR_I(PutFloat(buf, 5, s->t * s->scale));
|
|
ERR_I(StrPut(buf, " ", StrNONE));
|
|
ERR_I(StrPut(buf, units, StrNONE));
|
|
}
|
|
} else {
|
|
ERR_I(StrPut(buf, LscReadStat(s->readStat), StrNONE));
|
|
}
|
|
if (s==ctlSens) {
|
|
ERR_I(StrPut(buf, ", setpoint", '='));
|
|
if (tr==DATA_UNDEF) {
|
|
ERR_I(PutFloat(buf, 5, 0.0));
|
|
} else {
|
|
ERR_I(PutFloat(buf, 5, tr));
|
|
}
|
|
ERR_I(StrPut(buf, " ", StrNONE));
|
|
ERR_I(StrPut(buf, units, StrNONE));
|
|
}
|
|
if (s->lim > 0 && lim!=0) {
|
|
ERR_I(StrPut(buf, ", for T", lim));
|
|
ERR_I(PutFloat(buf, 5, s->lim));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int StatusHdl(int mode, void *base, int fd) {
|
|
int i, stat, typ;
|
|
StrBuf buf;
|
|
float tM, tS;
|
|
SensorT *s;
|
|
char pendAct[256];
|
|
|
|
readTemp=1;
|
|
StrLink(&buf, status);
|
|
StrClear(&buf);
|
|
ERR_I(StrPut(&buf, "\n", StrNONE));
|
|
if (noResp==3) {
|
|
ERR_I(StrPut(&buf, "no connection or controller switched off", StrNONE));
|
|
goto EndStatus;
|
|
}
|
|
if (statusBuf[0]!='\0') {
|
|
ERR_I(StrPut(&buf, "configuring:", ' '));
|
|
ERR_I(StrPut(&buf, statusBuf, StrNONE));
|
|
goto EndStatus;
|
|
}
|
|
CocShowHandlers(pendAct, sizeof(pendAct));
|
|
if (pendAct[0]!='\0') {
|
|
if (mode==COC_RD) {
|
|
return COC_DRD;
|
|
} else {
|
|
ERR_I(StrPut(&buf, "pending action(s):", ' '));
|
|
ERR_I(StrPut(&buf, pendAct, StrNONE));
|
|
goto EndStatus;
|
|
}
|
|
}
|
|
if (device[0]=='\0') {
|
|
ERR_I(StrPut(&buf, "no device selected", ' '));
|
|
goto EndStatus;
|
|
}
|
|
if (remoteMode==1) {
|
|
ERR_I(StrPut(&buf, "LOCAL mode, enter 'remote' to enable remote control", '\n'));
|
|
}
|
|
ERR_I(StrPut(&buf, "device:", ' '));
|
|
ERR_I(StrPut(&buf, device, StrNONE));
|
|
if (set==0) {
|
|
ERR_I(StrPut(&buf, "\nheater off,",' '));
|
|
} else {
|
|
ERR_I(StrPut(&buf, "\ntarget", '='));
|
|
ERR_I(PutFloat(&buf, 5, set));
|
|
if (ramp==0 || tr==setH) {
|
|
ERR_I(StrPut(&buf, " K,", ' '));
|
|
} else {
|
|
ERR_I(StrPut(&buf, " K ramping at", ' '));
|
|
ERR_I(PutFloat(&buf, 4, ramp));
|
|
ERR_I(StrPut(&buf, " K/min,", ' '));
|
|
}
|
|
}
|
|
if (relay) {
|
|
if (alarmChannels[0]!='\0') {
|
|
ERR_I(StrPut(&buf, "alarm on channel",' '));
|
|
ERR_I(StrPut(&buf, alarmChannels, StrNONE));
|
|
} else if (alarmHistory[0]!='\0') {
|
|
ERR_I(StrPut(&buf, "alarm was on channel", ' '));
|
|
ERR_I(StrPut(&buf, alarmHistory, ','));
|
|
ERR_I(StrPut(&buf, " (enter 'reset' to confirm)", StrNONE));
|
|
} else {
|
|
ERR_I(StrPut(&buf, "alarm",' '));
|
|
}
|
|
} else if (htrst!=0) {
|
|
ERR_I(StrPut(&buf, LscHtrStat(htrst), StrNONE));
|
|
} else {
|
|
if (power!=DATA_UNDEF) {
|
|
ERR_I(StrPut(&buf, "htr power", '='));
|
|
if (power>=0.5) {
|
|
ERR_I(PutFloat(&buf, 3, power));
|
|
ERR_I(StrPut(&buf, " W, htr current", '='));
|
|
} else {
|
|
ERR_I(PutFloat(&buf, 3, power*1000));
|
|
ERR_I(StrPut(&buf, " mW, htr current", '='));
|
|
}
|
|
ERR_I(PutFloat(&buf, 4, htr));
|
|
ERR_I(StrPut(&buf, "% ", '('));
|
|
ERR_I(PutFloat(&buf, 4, sqrt(power/resist)));
|
|
ERR_I(StrPut(&buf, " A", ')'));
|
|
} else {
|
|
ERR_I(StrPut(&buf, "set=0", StrNONE));
|
|
}
|
|
}
|
|
tM=0; tS=0;
|
|
if (cryo.sensor1!=NULL) {
|
|
if (cryo.sensor1!=samp.sensor1) {
|
|
ERR_I(StrPut(&buf, "\nheat exchanger", ':'));
|
|
if (cryo.sensor2!=cryo.sensor1) {
|
|
ERR_I(StrPut(&buf, " T", '='));
|
|
ERR_I(PutFloat(&buf, 4, cryo.temp));
|
|
ERR_I(StrPut(&buf, " ", 'K'));
|
|
ERR_I(ShowSensor(&buf, cryo.sensor1, "T", "K", '>'));
|
|
}
|
|
ERR_I(ShowSensor(&buf, cryo.sensor2, "T", "K", '<'));
|
|
ERR_I(StrPut(&buf, "\nsample:", ' '));
|
|
}
|
|
if (samp.sensor2!=samp.sensor1) {
|
|
ERR_I(StrPut(&buf, " T", '='));
|
|
ERR_I(PutFloat(&buf, 4, samp.temp));
|
|
ERR_I(StrPut(&buf, " ", 'K'));
|
|
ERR_I(ShowSensor(&buf, samp.sensor1, "T", "K", '>'));
|
|
}
|
|
ERR_I(ShowSensor(&buf, samp.sensor2, "T", "K", '<'));
|
|
}
|
|
if (testSens!=NULL || nScan>0) {
|
|
ERR_I(StrPut(&buf, "\ntest", ':'));
|
|
}
|
|
if (testSens!=NULL) {
|
|
ERR_I(ShowSensor(&buf, testSens, "T", "K", 0));
|
|
}
|
|
for (i=4; i<4+nScan; i++) {
|
|
ERR_I(ShowSensor(&buf, sensors[i], "T", "K", 0));
|
|
}
|
|
if (auxSens!=NULL) {
|
|
ERR_I(StrPut(&buf, "\nauxilliary", ':'));
|
|
ERR_I(ShowSensor(&buf, auxSens, "U", "V", 0));
|
|
}
|
|
if (heliumSens!=NULL) {
|
|
ERR_I(StrPut(&buf, "\nhelium:", ' '));
|
|
ERR_I(StrPut(&buf, helium, StrNONE));
|
|
}
|
|
if (still!=0) {
|
|
ERR_I(StrPut(&buf, "\nstill:", ' '));
|
|
ERR_I(PutFloat(&buf, 1, still));
|
|
ERR_I(StrPut(&buf, " mW", ' '));
|
|
}
|
|
EndStatus:
|
|
ERR_I(StrPut(&buf, "", '\0'));
|
|
return 0;
|
|
OnError:
|
|
return -1;
|
|
}
|
|
|
|
int PidSumHdl(int mode, void *base, int fd) {
|
|
StrBuf buf;
|
|
|
|
readTemp=1;
|
|
StrLink(&buf, pid);
|
|
StrClear(&buf);
|
|
ERR_I(PutFloat(&buf, 5, prop));
|
|
ERR_I(StrPut(&buf, " ", StrNONE));
|
|
ERR_I(PutFloat(&buf, 5, integ));
|
|
ERR_I(StrPut(&buf, " ", StrNONE));
|
|
ERR_I(PutFloat(&buf, 4, deriv));
|
|
ERR_I(StrPut(&buf, " /", ' '));
|
|
ERR_I(PutFloat(&buf, 4, prop*sqrt(scalPower/resist)/600));
|
|
ERR_I(StrPut(&buf, " A/K,", ' '));
|
|
ERR_I(PutFloat(&buf, 4, 1000.0/integ));
|
|
ERR_I(StrPut(&buf, " sec,", ' '));
|
|
ERR_I(PutFloat(&buf, 4, deriv));
|
|
ERR_I(StrPut(&buf, " sec", StrNONE));
|
|
return 0;
|
|
OnError:
|
|
return -1;
|
|
}
|
|
|
|
int RemoteHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
ERR_P(LscCmd(ser, "MODE:[remoteMode]"));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int RelayHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
if (alarmChannels[0]!='\0') ERR_MSG("alarm is still active");
|
|
return COC_DWR;
|
|
} else if (mode==COC_DWR) {
|
|
if (relay) {
|
|
ERR_P(LscCmd(ser, "RELAY 1:2,1"));
|
|
if (alarmHistory[0]=='\0') {
|
|
str_copy(alarmHistory, "X");
|
|
}
|
|
} else {
|
|
alarmHistory[0]='\0';
|
|
alarmStatus[0]='\0';
|
|
ERR_P(LscCmd(ser, "ALMRST;RELAY 1:1"));
|
|
logfileOut(LOG_MAIN, "reset alarms\n");
|
|
relay0=0;
|
|
lockAlarm=0;
|
|
set=0;
|
|
}
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int TmoHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
ERR_I(SerSetTmo(ser, msecTmo));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int SerHdl(int mode, void *base, int fd) {
|
|
if (mode==COC_WR) {
|
|
return COC_DRD;
|
|
} else if (mode==COC_DRD) {
|
|
SerClose(ser);
|
|
noResp=1;
|
|
ERR_P(ser=SerOpen(host, msecTmo, IdleHdl));
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int LogfileHdl(int mode, void *base, int fd) {
|
|
char buf[256];
|
|
if (mode==COC_WR) {
|
|
logfileClose();
|
|
str_copy(buf, logDir);
|
|
str_append(buf, serverId);
|
|
logfile=logfileInit(buf, logIt, use_stdout, logIt && use_stdout);
|
|
CocDefStr(logfile, COC_RDONLY);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ExecuteRequest(void) {
|
|
if (readTemp) ERR_I(ReadTemp());
|
|
ERR_I(CocCallHandlers());
|
|
while (settingsFlag==1) {
|
|
settingsFlag=0;
|
|
ERR_I(Settings());
|
|
}
|
|
statusBuf[0]='\0';
|
|
return 0;
|
|
OnError:
|
|
return -1;
|
|
}
|
|
|
|
int MainBody(void) {
|
|
int i, iret, tdif;
|
|
|
|
logfileWrite(logMask);
|
|
|
|
while (!quit) {
|
|
tdif = per - mycMsecSince(tim0);
|
|
if (tdif<0) { tim = mycNow(); break; } /* timeout */
|
|
ERR_I(iret=CocHandleRequests(tdif, 0));
|
|
tim=mycNow();
|
|
if (iret==0) { /* timeout */
|
|
break;
|
|
}
|
|
if (ser!=NULL) {
|
|
ERR_I(ExecuteRequest());
|
|
}
|
|
logfileWrite(logMask);
|
|
}
|
|
tdif = mycMsecSince(tim0);
|
|
if (tdif>60000 && cntError < 2) {
|
|
logfileOut(LOG_MAIN ,"%d seconds lost\n", tdif/1000);
|
|
}
|
|
tim0 = mycMsecSince(0)/period*period;
|
|
|
|
if (ser!=NULL) {
|
|
ERR_I(PeriodicTask());
|
|
ERR_I(ExecuteRequest());
|
|
}
|
|
|
|
return 0;
|
|
OnError:
|
|
if (0==strcmp(ErrMessage, "timeout")) {
|
|
if (noResp==2) { /* this is the second time we have no response */
|
|
per=1000; /* 1 sec */
|
|
cryo.temp=0;
|
|
samp.temp=0;
|
|
/* remoteMode=1; */
|
|
noResp=3;
|
|
} else if (noResp < 2) {
|
|
logfileOut(LOG_ALL ,"no response\n");
|
|
noResp=2;
|
|
per=100; /* try again soon */
|
|
}
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int i, iret;
|
|
char *inistr;
|
|
char buf[256], opt;
|
|
|
|
signal(SIGPIPE, ignore_forever);
|
|
|
|
#define RD COC_RDONLY
|
|
#define RW COC_RDWR
|
|
#define RA COC_RDWRALL
|
|
|
|
CocDefStruct(cryo, Testpoint);
|
|
CocDefStruct(samp, Testpoint);
|
|
CocDefPtr(tpoint, Testpoint);
|
|
|
|
CocFltFld(Testpoint, temp, RD);
|
|
CocFltFld(Testpoint, t1, RD);
|
|
CocFltFld(Testpoint, t2, RD);
|
|
|
|
CocDefStruct(sensA, SensorT);
|
|
CocDefStruct(sensB, SensorT);
|
|
CocDefStruct(sensC, SensorT);
|
|
CocDefStruct(sensD, SensorT);
|
|
CocDefStruct(sensA1, SensorT);
|
|
CocDefStruct(sensA2, SensorT);
|
|
CocDefStruct(sensA3, SensorT);
|
|
CocDefStruct(sensA4, SensorT);
|
|
CocDefPtr(sens, SensorT);
|
|
|
|
CocFltFld(SensorT, t, RD);
|
|
CocFltFld(SensorT, t0, RD);
|
|
CocFltFld(SensorT, t1, RD);
|
|
CocFltFld(SensorT, t2, RD);
|
|
CocFltFld(SensorT, lim, RD);
|
|
CocFltFld(SensorT, scale, RD);
|
|
CocFltFld(SensorT, alarm, RW); CocHdl(AlarmHdl);
|
|
CocIntFld(SensorT, readStat, RD);
|
|
CocIntFld(SensorT, stat1, RD);
|
|
CocIntFld(SensorT, stat2, RD);
|
|
CocStrFld(SensorT, ch, RD);
|
|
|
|
CocDefFlt(maxPower, RW); CocHdl(MaxPowerHdl);
|
|
CocDefFlt(slope, RW); CocHdl(MaxPowerHdl);
|
|
CocDefFlt(prop, RW); CocHdl(PidHdl);
|
|
CocDefFlt(integ, RW); CocHdl(PidHdl);
|
|
CocDefFlt(deriv, RW); CocHdl(PidHdl);
|
|
CocDefFlt(set, RW); CocHdl(SetHdl);
|
|
CocDefFlt(ramp, RW); CocHdl(SetHdl);
|
|
CocDefFlt(still, RW); CocHdl(StillHdl);
|
|
CocDefFlt(scalPower, RD);
|
|
CocDefFlt(smooth, RW);
|
|
CocDefFlt(powFact, RW);
|
|
CocDefFlt(resist, RD);
|
|
CocDefFlt(htr, RD);
|
|
CocDefFlt(power, RD);
|
|
CocDefFlt(setH, RD);
|
|
CocDefFlt(full, RW);
|
|
CocDefFlt(tLimit, RD);
|
|
CocDefFlt(maxShift, RW);
|
|
CocDefFlt(tm, RD);
|
|
CocDefFlt(ts, RD);
|
|
CocDefFlt(tr, RD);
|
|
CocDefFlt(te, RD);
|
|
CocDefFlt(aux, RD);
|
|
CocDefFlt(he, RD);
|
|
CocDefFlt(fbuf, RD);
|
|
CocDefFlt(r1, RD);
|
|
CocDefFlt(r2, RD);
|
|
CocDefFlt(tShift, RW);
|
|
CocDefFlt(tInt, RW);
|
|
|
|
CocDefPtr(clData, ClientData);
|
|
CocStrFld(ClientData, cmd, RW); CocHdl(SendHdl);
|
|
CocIntFld(ClientData, logstart, RA);
|
|
CocStrFld(ClientData, logline, RA); CocHdl(LogHdl);
|
|
|
|
CocAlias(send, clData.cmd);
|
|
CocAlias(logstart, clData.logstart);
|
|
CocAlias(logline, clData.logline);
|
|
|
|
CocDefStr(device, RW); CocHdl(DeviceHdl);
|
|
CocDefStr(buf1, RD);
|
|
CocDefStr(buf2, RD);
|
|
CocDefStr(buf3, RD);
|
|
CocDefStr(buf4, RD);
|
|
CocDefStr(head, RD);
|
|
CocDefStr(chan, RD);
|
|
CocDefStr(helium, RD);
|
|
CocDefStr(heUnits, RD);
|
|
CocDefStr(intype, RD);
|
|
CocDefStr(status, RD); CocHdl(StatusHdl);
|
|
CocDefStr(pid, RD); CocHdl(PidSumHdl);
|
|
CocDefStr(config, RD);
|
|
|
|
CocDefInt(cod1, RD);
|
|
CocDefInt(cod2, RD);
|
|
CocDefInt(out1, RD);
|
|
CocDefInt(out2, RD);
|
|
CocDefInt(num, RD);
|
|
CocDefInt(key, RD);
|
|
CocDefInt(maxfld, RD);
|
|
CocDefInt(iAmp, RD);
|
|
CocDefInt(iRange, RD);
|
|
CocDefInt(remoteMode, RW); CocHdl(RemoteHdl);
|
|
CocDefInt(relay, RW); CocHdl(RelayHdl);
|
|
CocDefInt(htrst, RD);
|
|
CocDefInt(loop, RD);
|
|
CocDefInt(rdTim, RD);
|
|
CocDefInt(tim0, RD);
|
|
|
|
CocDefInt(logMask, RW);
|
|
CocDefInt(logPeriod, RW);
|
|
CocDefInt(readTemp, RW);
|
|
CocDefInt(controlMode, RW);
|
|
CocDefInt(int2, RW);
|
|
CocDefInt(busy, RD);
|
|
CocDefInt(serialNo, RD);
|
|
CocDefInt(quit, RW);
|
|
CocDefInt(nScan, RD);
|
|
|
|
CocDefStr(grapar, RA);
|
|
CocDefArr(gradata, RD); CocHdl(GraHdl); grasize=CocSizePtr();
|
|
|
|
CocAlias(tempX,cryo.temp);
|
|
CocAlias(tempP,samp.temp);
|
|
CocAlias(Ta,sensA.t);
|
|
CocAlias(Tb,sensB.t);
|
|
CocAlias(Tc,sensC.t);
|
|
CocAlias(Td,sensD.t);
|
|
CocAlias(T1,sensA1.t);
|
|
CocAlias(T2,sensA2.t);
|
|
CocAlias(T3,sensA3.t);
|
|
CocAlias(T4,sensA4.t);
|
|
CocAlias(P,power);
|
|
CocAlias(tempC, set);
|
|
CocAlias(int,integ);
|
|
|
|
CocDefInt(msecTmo, RW); CocHdl(TmoHdl);
|
|
CocDefStr(host, RW); CocHdl(SerHdl);
|
|
CocDefInt(port, RD);
|
|
CocDefInt(use_stdout, RW); CocHdl(LogfileHdl);
|
|
CocDefStr(serverId, RW); CocHdl(LogfileHdl);
|
|
CocDefInt(logIt, RW); CocHdl(LogfileHdl);
|
|
CocDefStr(logDir, RW); CocHdl(LogfileHdl);
|
|
CocDefStr(binDir, RW);
|
|
|
|
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++;
|
|
str_copy(serverId, argv[i]);
|
|
} else if ('b'==opt) {
|
|
i++;
|
|
str_copy(binDir, argv[i]);
|
|
} else if ('d'==opt) {
|
|
i++;
|
|
str_copy(logDir, argv[i]);
|
|
} else if ('t'==opt) {
|
|
i++;
|
|
msecTmo=atoi(argv[i]);
|
|
} else if ('h'==opt) {
|
|
i++;
|
|
str_copy(host, argv[i]);
|
|
} else if ('p'==opt) {
|
|
i++;
|
|
port=atoi(argv[i]);
|
|
} else if ('f'==opt) {
|
|
i++;
|
|
logPeriod=atoi(argv[i]);
|
|
} else {
|
|
if (NULL!=strchr(argv[i], '=')) {
|
|
CocReadVars(argv[i], '\0');
|
|
} else {
|
|
inistr=str_read_file(argv[i]);
|
|
if (inistr==NULL) {
|
|
logfileOut(LOG_MAIN ,"?");
|
|
} else {
|
|
CocReadVars(inistr, '\0');
|
|
free(inistr);
|
|
}
|
|
}
|
|
}
|
|
if (opt!=' ') logfileOut(LOG_MAIN ,"-%c ", opt);
|
|
logfileOut(LOG_MAIN ,"%s ", argv[i]);
|
|
}
|
|
}
|
|
|
|
assert(logPeriod>0 && host[0]!='\0' && port!=0 && msecTmo>0);
|
|
|
|
str_copy(statusBuf, "starting up");
|
|
logfileStatusBuf(statusBuf);
|
|
|
|
str_copy(buf, logDir);
|
|
str_append(buf, serverId);
|
|
logfile=logfileInit(buf, logIt, use_stdout, logIt && use_stdout);
|
|
CocDefStr(logfile, RD);
|
|
logfileOut(LOG_MAIN ,"\n");
|
|
logfileWrite(logMask);
|
|
|
|
ERR_I(CocInitServer(SetClientData, port));
|
|
|
|
ser=SerOpen(host, msecTmo, IdleHdl);
|
|
if (ser==NULL) {
|
|
str_copy(statusBuf, "can not connect to serial port server or terminal server");
|
|
logfileShowErr("error in SerOpen");
|
|
}
|
|
ERR_I(iret=CocHandleRequests(100, 0));
|
|
tim0=mycMsecSince(0)/period*period;
|
|
tim=mycNow();
|
|
|
|
ERR_P(DataCreateSet(NULL, "Tm", &tm, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "Ts", &ts, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "Tr", &tr, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "Te", &te, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "He", &he, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "T1", &sensA1.t, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "T2", &sensA2.t, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "T3", &sensA3.t, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "T4", &sensA4.t, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "Aux", &aux, 5, LOGLIFETIME, tim));
|
|
ERR_P(DataCreateSet(NULL, "P", &power, 5, LOGLIFETIME, tim));
|
|
|
|
remoteMode=2;
|
|
prop=50;
|
|
integ=20;
|
|
deriv=0;
|
|
if (ser!=NULL) {
|
|
LscCmd(ser, "MODE?>remoteMode");
|
|
LoadFromLsc();
|
|
}
|
|
per=1; /* advance fast when initializing */
|
|
cntError=0;
|
|
while (!quit) {
|
|
iret=MainBody();
|
|
if (iret<0 || ser==NULL) {
|
|
cntError++;
|
|
ser=SerCheck(ser);
|
|
if (0==strcmp(ErrMessage, "asynsrv error")) {
|
|
if (ser!=NULL) SerClose(ser);
|
|
ser=NULL;
|
|
noResp=1;
|
|
}
|
|
if (cntError<4) {
|
|
if (iret<0) {
|
|
logfileShowErr("error in TecsServer/MainBody");
|
|
} else {
|
|
logfileShowErr("error in SerOpen");
|
|
}
|
|
} else if (cntError==4) {
|
|
logfileOut(LOG_MAIN, "--- too many errors: skip messages ---\n");
|
|
}
|
|
if (ser==NULL) {
|
|
CocHandleRequests(msecTmo, 0);
|
|
ser=SerOpen(host, msecTmo, IdleHdl);
|
|
if (ser==NULL) {
|
|
str_copy(statusBuf, "can not connect to serial port server or terminal server");
|
|
} else {
|
|
LscCmd(ser, "MODE?>remoteMode");
|
|
LoadFromLsc();
|
|
}
|
|
}
|
|
} else {
|
|
if (cntError>0) {
|
|
if (cntError>4) {
|
|
cntError=4;
|
|
}
|
|
cntError--;
|
|
}
|
|
}
|
|
}
|
|
LogMinMax(0);
|
|
logfileWrite(logMask);
|
|
if (quit==1) {
|
|
ERR_MSG("restart by quit command");
|
|
} else {
|
|
ERR_MSG("killed by quit command");
|
|
}
|
|
OnError:
|
|
printf("TecsServer exited: %s\n", ErrMessage);
|
|
logfileShowErr("exit TecsServer");
|
|
if (ser!=NULL) SerClose(ser);
|
|
CocCloseServer();
|
|
logfileClose();
|
|
return quit;
|
|
}
|