#include #include #include #include #include #include #include #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; } static SerChannel *ser=NULL; static char *serverId=NULL; static char *binDir=NULL; static char *logDir=NULL; static DlogSet dset; typedef struct { float temp, t1, t2; /* calc, high, low temperature */ int dirty; /* input config to be reloaded */ int try; /* trial count */ int manual; /* manual device */ int code, code1; /* device code, buffer for device code */ int nSens; /* number of sensors */ int codChanged; /* code has changed */ int codDefined; /* code is not yet confirmed */ float scale; /* scale for extreme ranges */ char ch1[2], ch2[2]; /* channels for high/low T */ char device[16]; /* device name */ char tname[16]; } Testpoint; Testpoint /* C standard guarantees initialization to zero */ cryo, /* data for main sensors (on heat exchanger, or the only sensors) */ samp, /* data for extra sensors of sample stick */ *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 */ tInt=0; /* integral time (sec.) for setpoint shift */ static int logPeriod=10, /* data logging period (sec.) */ period=5000, /* default read interval (msec.) */ logTime, /* next logging time */ setFlag, /* temperature to be set */ saveTime, /* time for a CRVSAV command */ noResp=1, /* no response */ quit, /* quit server */ controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */ mode=2, /* 0: local, 2: remote */ maxfld, /* last used display field */ busy, /* busy after CRVSAV */ deviceFlag, /* device given via net */ num, /* curve number */ fld, /* field number */ key, /* key status */ serialNo, configuring=1, resist, /* heater resistance */ readTemp, /* client requested readTemp */ cod1, cod2, out1, out2, /* codes read from digital input/output */ iRange, iAmp, /* max. range and max. current code */ per; /* effective period */ static time_t auto_remote_time, /* time for automatic reload */ tim, /* actual time */ tableTime; /* last time when table was read */ static int decod[8]={21,20,17,16,5,4,1,0}; /* for code conversion */ static char status[132], /* status buffer */ device[32], /* concatenated device names */ buf1[256], buf2[256], buf3[256], buf4[256], /* buffers for temporary use */ head[64], /* curve header */ intype[64], /* input configuration */ chan[2]; /* actual channel */ static char *table=NULL, /* environment devices table */ *cache=NULL; /* curve list cache */ struct timeb tim0; int logMask; void idleHdl(int tmo, int fd) { int iRet; iRet=CocHandleRequests(tmo, fd); if (iRet<0) logfileShowErr("CocHandleRequests"); } void concatDevice(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); } } int instCurve(char *nam, char *channel) { /* install sensor nam on channel */ char buf[256], chead[64], nbuf[256], lbuf[16]; char *crv, *entry, *points, *start, *s, /* start of found entry */ *e, /* cache part after found entry */ *res, *t; int i, n; char used[60]; FILE *fil; int retstat; fil=NULL; crv=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 (points[0]=='$') { /* standard curve */ points++; num=atoi(points); if (num>20) ERR_MSG("illegal standard curve number"); retstat=-1; /* an error could be fixed */ ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); } else { strcpy(buf, ":"); str_append(buf, nam); str_append(buf, " "); str_upcase(buf, buf); if (cache==NULL) { ERR_SP(cache=my_malloc(1,"one")); *cache='\0'; } /* create empty cache if undefined */ start=strchr(cache, '\n'); /* skip device names */ if (start==NULL) { start=cache; } else { start++; } entry=strstr(start, buf); if (entry==NULL) { /* sensor not found in cache */ entry=start; for (i=60;i>20;i--) used[i]=0; n=40; num=0; while (entry!=NULL && n>0) { i=0; sscanf(entry, "%d", &i); if (i>20 && i<=60) { num=i; s=entry; used[i]=1; n--; } entry=strchr(entry, '\n'); if (entry !=NULL) entry++; } if (n>0) { for (num=60;num>20;num--) { if (used[num]==0) break; } s=NULL; e=NULL; } else { e=strchr(s, '\n'); if (e!=NULL) { *e='\0'; e++; } if (s>start) { s--; *s='\0'; } } head[0]='\0'; } else { s=entry; entry++; while (s>start && *s!='\n') s--; if (s>start) { *s='\0'; s++; } num=0; sscanf(s, "%d", &num); if (num<21 || num>60) ERR_MSG("illegal curve number"); retstat=-1; /* an error could be fixed */ ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); e=strchr(entry, '\n'); if (e!=NULL) { *e='\0'; e++; } } } fld=chan[0]-'A'+1; if (fld>maxfld) maxfld=fld; if (head[0]!='\0' && LscEqPar(head, chead)) { /* header matches: select sensor type and curve */ retstat=-1; /* an error could be fixed */ ERR_P(LscCmd(ser, "INTYPE [chan]:[intype];INCRV [chan]:[num];DISPFLD [fld],[chan],1;DISPLAY:[maxfld]")); logfileOut(LOG_MAIN, "curve %d on channel %s selected\n", num, chan); 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, "INTYPE [chan]:[intype];DISPFLD [fld],[chan],3;DISPLAY:[maxfld]")); Progress(1); n=3; do { ERR_P(LscCmd(ser, "CRVDEL [num];CRVHDR?[num]>buf1,")); buf1[4]='\0'; i=strcmp(buf1, "User"); n--; } while (i!=0 && n!=0); if (i!=0) ERR_MSG("can not delete curve"); sprintf(lbuf, "CRVPT %d", num); i=0; do { /* download curve */ t=str_split(nbuf, points, '\n'); if (nbuf[0]!='\0') { ERR_I(str_substitute(buf, nbuf, "#0", lbuf)); ERR_P(LscCmd(ser, buf)); i++; if (i%10==0) sprintf(status, "downloading curve at line %d", i); Progress(1); } points=t; } while (t!=NULL); /* write header, select curve */ str_upcase(head, chead); ERR_P(LscCmd(ser, "CRVHDR [num]:[head];INCRV [chan]:[num];DISPFLD [fld],[chan],1")); Progress(1); logfileOut(LOG_MAIN, "curve selected on channel %s\n", chan); saveTime=tim+30; } 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")); if (cryo.manual) ERR_SI(fputs(cryo.device, fil)); ERR_SI(fputs("/", fil)); if (samp.manual) ERR_SI(fputs(samp.device, fil)); ERR_SI(fputs("\n", fil)); sprintf(buf, "%d:%s", num, head); ERR_SI(fputs(buf, fil)); /* write actual entry */ if (start!=s) { /* write content before replaced entry */ ERR_SI(fputs("\n", fil)); ERR_SI(fputs(start, fil)); } if (e!=NULL) { /* write content after replaced entry */ ERR_SI(fputs("\n", fil)); ERR_SI(fputs(e, fil)); } ERR_SI(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; 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) { samp.nSens=0; i=sscanf(t, "%12s%d%d", nam, &nn, &n); if (i<1) ERR_MSG("missing sensor name"); ext=".s"; } else { cryo.nSens=0; tLow=0; tHigh=0; controlMode=0; i=sscanf(t, "%12s%d%d%d%f%d%f%f%f", nam, &n, &nn, &controlMode, &tLimit, &resist, &power, &tLow, &tHigh); if (i<7) ERR_MSG("missing some sensor parameters"); ext=".x"; } if (n<0 || n>2) ERR_MSG("illegal value for nsensor"); if (n==0) return(0); nam[strlen(nam)-1]='\0'; /* strip off quote */ if (!tpoint->manual) { /* set device name */ str_copy(tpoint->device, nam); concatDevice(); } str_append(nam, ext); ERR_I(retstat=instCurve(nam, tpoint->ch1)); if (n==2) { str_append(nam, "l"); ERR_I(retstat=instCurve(nam, tpoint->ch2)); } tpoint->nSens=n; 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")); if (cryo.manual) ERR_SI(fputs(cryo.device, fil)); ERR_SI(fputs("/", fil)); if (samp.manual) ERR_SI(fputs(samp.device, fil)); ERR_SI(fputs("\n", fil)); bufi[0]=buf1; bufi[1]=buf2; bufi[2]=buf3; bufi[3]=buf4; for (i=60; i>21; i-=4) { sprintf(buf, "CRVHDR?%d>buf1;CRVHDR?%d>buf2;CRVHDR?%d>buf3;CRVHDR?%d>buf4", i, i-1, i-2, i-3); Progress(1); ERR_P(LscCmd(ser, buf)); k=0; for (j=i; j>i-4; j--) { res=bufi[k]; k++; if (res[1]=='s') { i=0; break;} /* s of "User", must be empty slot, lowercase letters are not programmable */ sprintf(buf, "%d:", j); ERR_SI(fputs(buf, fil)); ERR_SI(fputs(res, fil)); ERR_SI(fputs("\n", fil)); } } ERR_SI(fclose(fil)); /* re-read cache */ ERR_P(cache=str_read_file(nbuf)); return(0); OnError: if (fil!=NULL) fclose(fil); return(-1); } float WeightedAverage(int n, float tH, float tL) { float p,q; if (n==0) { return(0.0); } else if (n<2) { return(tH); } else { if (tL1 && tempC<(tLow+tHigh)/2) ch=cryo.ch2; if (samp.nSens>0) { if (controlMode==1) { /* control directly on sample sensor */ tShift=0; ch=samp.ch1; if (cryo.nSens>1 && tempC<(tLow+tHigh)/2) ch=samp.ch2; scale=samp.scale; } else if (controlMode!=2) { tShift=0; } } else { tShift=0; } str_copy(chan, ch); if (scale!=1.0) { ERR_P(LscCmd(ser, "LINEAR C,1,0,1,1,[tempC]")); } if (tempC==0) { ERR_P(LscCmd(ser, "RANGE:0;SETP 1:0")); return(0); } tempH=(tempC+tShift)/scale; 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; readTemp=0; buf[0]='\0'; if (cryo.nSens>0) { str_append(buf, "KRDG?[cryo.ch1]>cryo.t1;"); if (cryo.nSens>1) { str_append(buf, "KRDG?[cryo.ch2]>cryo.t2;"); } else { cryo.t2=0; } } else { cryo.t1=0; cryo.t2=0; } if (samp.nSens>0) { str_append(buf, "KRDG?[samp.ch1]>samp.t1;"); if (samp.nSens>1) { str_append(buf, "KRDG?[samp.ch2]>samp.t2;"); } else { samp.t2=0; } } else { samp.t1=0; samp.t2=0; } i=strlen(buf); if (i>0) { buf[i-1]='\0'; /* strip off ';' */ ERR_P(LscCmd(ser, buf)); } cryo.temp=WeightedAverage(cryo.nSens, cryo.t1, cryo.t2)*cryo.scale; samp.temp=WeightedAverage(samp.nSens, samp.t1, samp.t2)*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) { str_copy(status, "configuring"); configuring=1; } return(0); OnError: return(-1); } int PeriodicTask(void) { char buf[256], lbuf[16]; char *res; int i, k; time_t putTim; float t2[2], p, d, w; ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;HTR?>htr;BUSY?>busy")); if (cryo.codDefined) { per=period; } else { per=1; /* advance fast when initializing */ } if (noResp) { /* check serial number */ k=serialNo; ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo,")); if (0!=strcmp(buf1, "LSCI") || 0!=strcmp(buf2, "MODEL340") || serialNo==0) return(0); if (k!=serialNo) { if (!configuring) { str_copy(status, "controller connected"); } configuring++; tempC=0; if (cryo.manual || cryo.code!=0) { cryo.dirty=1; } if (samp.manual || samp.code!=0) { samp.dirty=1; } ERR_P(LscCmd(ser, "RANGE:0")); /* switch off heater */ /* reload curve cache: */ if (cache!=NULL) 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()); cryo.device[0]='\0'; samp.device[0]='\0'; sscanf(cache, "%15[^/!]%*c%15[^\n!]", cryo.device, samp.device); /* read device names separated by '/' */ if (cryo.device[0]!='\0') cryo.manual=1; if (samp.device[0]!='\0') samp.manual=1; concatDevice(); } noResp=0; } ERR_I(ReadTemp()); if (cryo.dirty==0 && samp.dirty==0 && noResp==0 && tim>logTime) { t2[0]=cryo.temp; t2[1]=samp.temp; time(&putTim); DlogPut(&dset, putTim, 2, t2); DlogUpd(&dset); logTime=(putTim/logPeriod+1)*logPeriod; time(&tim); if (tim-putTim>1) { logfileOut(LOG_MAIN, "needed %d sec. for filling in dlog\n", tim-putTim); } } if (samp.nSens>0 && cryo.nSens>0 && controlMode==2 && tempC!=0) { d=(tempH-cryo.temp)/cryo.temp-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 (tInt<30000/period) tInt+=w; /* increase integral time until 30 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) { tpoint->code=tpoint->code1; tpoint->codChanged=1; } else { if (tpoint->codChanged) { 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); } if (tpoint->codDefined) { tpoint->manual=0; } tempC=0; tpoint->dirty=1; if (!configuring) configuring=1; } tpoint->codDefined=1; } } } } if (key!=0) { auto_remote_time=tim+600; if (!(cryo.dirty || samp.dirty)) { logfileOut(LOG_MAIN ,"user touched keys\n"); } if (cryo.manual || cryo.code!=0) cryo.dirty=1; if (samp.manual || samp.code!=0) samp.dirty=1; mode=0; ERR_P(LscCmd(ser, "MODE?>mode")); if (mode==2) auto_remote_time=tim; /* user switched to remote mode */ } return(0); OnError: return(-1); } int inputSettings(Testpoint *this) { 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->nSens=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"); } } else { ERR_P(LscCmd(ser, "ALARM [tpoint.ch1]:[tpoint.nSens],1,[tLimit],0,0,1;ALARM [tpoint.ch2]:0;RELAY 1:1;BEEP:0")); } } } return(0); OnError: return(-1); } int Settings(void) { int i, j, k; float pa, pr, pw, dif; char nbuf[256], buf[256], *cfg, *p; cfg=NULL; if (cryo.dirty && cryo.codDefined || samp.dirty && samp.codDefined) { for (i=0; i<2; i++) { tpoint=tpoints[i]; if (tpoint->dirty) { ERR_P(LscCmd(ser, "DISPFLD 2,[tpoint.ch1],1;DISPFLD 4,[tpoint.ch2],1")); } } inputSettings(&cryo); inputSettings(&samp); if (cryo.nSens>0) { /* control settings */ ERR_P(LscCmd(ser, "CDISP 1:1,[resist],1;MOUT 1:0;CMODE 1:1")); iAmp=1; iRange=0; if (power>0) { pa=resist*4; /* max. power */ pw=0; dif=1.0e6; for (i=4; i>0; i--) { pr=pa; for (j=5; j>0; j--) { if (pr>power) { if (pr/power=cryo.nSens) { maxfld=2*samp.nSens; } else { maxfld=2*cryo.nSens-1; } if (maxfld>0) { ERR_P(LscCmd(ser, "MODE:2;DISPLAY:[maxfld]")); } else { maxfld=1; ERR_P(LscCmd(ser, "MODE:2;DISPLAY:1;DISPFLD 1,A,3")); } mode=2; 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); } 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; } ERR_I(ReadTemp()); } return(0); OnError: if (cfg!=NULL) my_free(cfg); return(-1); } int ExecuteRequest(void) { char *t, *res; struct CocClient *client; if (readTemp) ReadTemp(); if (tim>auto_remote_time || setFlag) ERR_I(Settings()); if (setFlag) { if (cryo.nSens>0) { tInt=0; /* reset integral time */ ERR_I(SetTemp(1)); } setFlag=0; } client=CocGetNextCmd(); if (client!=NULL) { if (NULL!=strchr(client->cmd, '>') || NULL!=strchr(client->cmd, '[')) ERR_MSG("no variables allowed"); res=LscCmd(ser, client->cmd); if (res==NULL && ErrMessage!=NULL) { str_copy(client->res, ErrMessage); } else { str_copy(client->res, res); } client->cmd[0]='\0'; } if (deviceFlag) { tempC=0; if (!configuring) { str_copy(status, "configuring"); configuring=1; } t=strchr(device, '/'); if (t==NULL) { if (0==strcmp(device, "0")) { cryo.manual=0; cryo.dirty=1; samp.manual=0; samp.dirty=1; } else { str_copy(cryo.device, device); str_copy(samp.device, device); cryo.manual=1; cryo.dirty=1; samp.manual=1; samp.dirty=1; } } else { if (t!=device) { *t='\0'; str_copy(cryo.device, device); *t='/'; cryo.manual=1; cryo.dirty=1; } t++; if (*t!='\0') { str_copy(samp.device, t); samp.manual=1; samp.dirty=1; } } concatDevice(); deviceFlag=0; } return(0); OnError: return(-1); } int mainBody(void) { int i, iret, tdif; struct timeb tim1; ERR_I(PeriodicTask()); if (tim>=auto_remote_time) ERR_I(Settings()); logfileWrite(logMask); while (!quit) { ftime(&tim1); tdif=per-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm); if (tdif<0) { tim=tim1.time; break; } /* timeout */ ERR_I(iret=CocHandleRequests(tdif, 0)); if (iret==0) { time(&tim); break; } /* timeout */ tim=tim1.time; ERR_I(ExecuteRequest()); logfileWrite(logMask); } ftime(&tim1); tdif=((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm)/period; i=period*tdif+tim0.millitm; tim0.time+=i / 1000; tim0.millitm=i % 1000; if (tdif>1) { logfileOut(LOG_INFO ,"%d cycles lost\n", tdif-1); } return(0); OnError: if (0==strcmp(ErrMessage, "timeout")) { if (!noResp) logfileOut(LOG_MAIN ,"no response\n"); per=period+10000; /* long period if no response */ noResp=1; cryo.temp=0; samp.temp=0; 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(cryo.ch1,"A"); str_copy(cryo.ch2,"B"); str_copy(samp.tname,"sample stick"); str_copy(samp.ch1,"C"); str_copy(samp.ch2,"D"); cryo.codChanged=1; cryo.scale=1.0; samp.codChanged=1; samp.scale=1.0; logMask=LOG_MAIN+LOG_INFO; binDir="bin/"; logDir="log/"; serverId="tecs"; host="lnsp26:4000/0"; port=0; msecTmo=0; logfileOut(LOG_INFO ,"%s ", argv[0]); for (i=1;i10) ERR_MSG("too many errors - quit"); logfileShowErr("error in TecsServer/mainBody"); } else { if (cntError>0) cntError--; } } ERR_P(LscCmd(ser, "MODE:1")); logfileWrite(logMask); ERR_MSG("got quit command"); OnError: logfileShowErr("exit TecsServer"); DlogClose(&dset); SerClose(ser); CocCloseServer(); return(0); }