805 lines
22 KiB
C
805 lines
22 KiB
C
#include <math.h>
|
|
#include <assert.h>
|
|
#include <sys/timeb.h>
|
|
#include <ctype.h>
|
|
#include "server.h"
|
|
#include "logfile.h"
|
|
#include "util.h"
|
|
#include "lsc.h"
|
|
#include "dlog.h"
|
|
|
|
#define TABLE_FILE "lsc.tab"
|
|
#define NO_CODE 999
|
|
|
|
static SerChannel *ser=NULL;
|
|
static char *serverId=NULL;
|
|
static char *binDir=NULL;
|
|
static char *logDir=NULL;
|
|
static DlogSet dset;
|
|
|
|
static float
|
|
tempP=0, /* sample T */
|
|
tempX=0, /* heat exch. T */
|
|
tempC=0, /* set T */
|
|
tempH=0, /* set T on heater */
|
|
htr; /* heat power */
|
|
|
|
static int
|
|
logPeriod=10, /* logging period (sec.) */
|
|
period=1000, /* default read interval (msec.) */
|
|
logTime=0, /* next logging time */
|
|
setFlag=0, /* temperature to be set */
|
|
remoteFlag=0, /* to be set to remote mode */
|
|
dirtyX=0, /* reload input config for heat exch. */
|
|
dirtyP=0, /* reload input config for sample */
|
|
tryP=0, /* trial count for sample */
|
|
tryX=0, /* trial count for heat exch */
|
|
saveIt=0, /* CRVSAV command */
|
|
noResp=1, /* no response */
|
|
manualX=0, /* X device was given manually */
|
|
manualP=0, /* P device was given manually */
|
|
quit=0, /* quit server */
|
|
controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */
|
|
serialNo=0;
|
|
|
|
static int busy, mode=0;
|
|
static int nX=0, nP=0; /* number of sensors */
|
|
static int maxfld; /* last used display field */
|
|
static float tLimit, resist=0.0, power; /* heater parameters */
|
|
static float tLow=0, tHigh=0; /* lower limit of high-T sensor, upper limit of low-T sensor */
|
|
static float tShift=0; /* setpoint shift */
|
|
static float tInt=0; /* integral time (sec.) for setpoint shift */
|
|
static time_t auto_remote_time=0; /* time for automatic reload */
|
|
static time_t tim; /* actual time */
|
|
static time_t tableTime; /* last time when table was read */
|
|
static int codX=-1, codP=0; /* codes for heat exchanger and sample */
|
|
static int decod[8]={21,20,17,16,5,4,1,0}; /* for code conversion */
|
|
static char channel[5]="ACBD"; /* sensor channels for heater and sample (main, lowT) */
|
|
static char device[32], deviceX[16], deviceP[16];
|
|
static int deviceFlag=0;
|
|
static char *table=NULL; /* environment devices table */
|
|
static char *cache=NULL; /* curve list cache */
|
|
|
|
void idleHdl(int tmo, int fd) {
|
|
int iRet;
|
|
|
|
iRet=CocHandleRequests(tmo, fd);
|
|
if (iRet<0) logfileShowErr("CocHandleRequests");
|
|
}
|
|
|
|
void concatDevice() {
|
|
str_copy(device, deviceX);
|
|
if (0!=strcmp(deviceX, deviceP)) {
|
|
str_append(device, "/");
|
|
str_append(device, deviceP);
|
|
}
|
|
}
|
|
|
|
int instCurve(char *nam, char chan) {
|
|
/*
|
|
install sensor nam on channel chan
|
|
*/
|
|
char *args[2];
|
|
char buf[256], head[64], nbuf[256], lbuf[16];
|
|
char *crv, *entry, *points, *intype, *start,
|
|
*s, /* start of found entry */
|
|
*e, /* cache part after found entry */
|
|
*res, *t;
|
|
int i, num, n, fld;
|
|
char used[60];
|
|
FILE *fil;
|
|
int retstat;
|
|
|
|
logfileOut("install curve %s\n", nam);
|
|
retstat=-2; /* errors in following section are severe */
|
|
fil=NULL;
|
|
crv=NULL;
|
|
strcpy(buf, ":");
|
|
str_append(buf, nam);
|
|
str_append(buf, " ");
|
|
str_upcase(buf);
|
|
|
|
if (cache==NULL) { cache=malloc(1); *cache='\0'; } /* create empty cache if undefined */
|
|
start=strchr(cache, '\n'); /* skip device names */
|
|
if (start==NULL) { start=cache; } else { start++; }
|
|
entry=strstr(start, buf);
|
|
if (entry==NULL) { /* sensor not found in cache */
|
|
entry=start;
|
|
for (i=60;i>20;i--) used[i]=0;
|
|
n=40; num=0;
|
|
while (entry!=NULL && n>0) {
|
|
i=0;
|
|
sscanf(entry, "%d", &i);
|
|
if (i>20 && i<=60) { num=i; s=entry; used[i]=1; n--; }
|
|
entry=strchr(entry, '\n');
|
|
if (entry !=NULL) entry++;
|
|
}
|
|
if (n>0) {
|
|
for (num=60;num>20;num--) { if (used[num]==0) break; }
|
|
s=NULL;
|
|
e=NULL;
|
|
} else {
|
|
e=strchr(s, '\n');
|
|
if (e!=NULL) { *e='\0'; e++; }
|
|
if (s>start) { s--; *s='\0'; }
|
|
}
|
|
head[0]='\0';
|
|
} else {
|
|
s=entry; entry++;
|
|
while (s>start && *s!='\n') s--;
|
|
if (s>start) { *s='\0'; s++; }
|
|
num=0;
|
|
sscanf(s, "%d", &num);
|
|
if (num<21 || num>60) ERR_MSG("illegal curve number");
|
|
sprintf(buf, "CRVHDR?%d", num);
|
|
retstat=-1; /* errors in following section are not severe */
|
|
ERR_P(res=SerCmd(ser, buf));
|
|
e=strchr(entry, '\n');
|
|
if (e!=NULL) { *e='\0'; e++; }
|
|
str_copy(head, res);
|
|
}
|
|
|
|
/* read and substitute curve file */
|
|
sprintf(buf, "CRVPT %d", num);
|
|
args[0]=buf;
|
|
retstat=-2; /* errors in following section are severe */
|
|
str_copy(nbuf, binDir);
|
|
str_append(nbuf, nam);
|
|
ERR_P(crv=str_read_arg(nbuf, args, 1));
|
|
|
|
intype=str_split1(crv, '\n');
|
|
if (intype==NULL) {
|
|
points=NULL;
|
|
} else {
|
|
points=str_split1(intype, '\n');
|
|
}
|
|
if (points==NULL) {
|
|
ERR_MSG("illegal curve file");
|
|
}
|
|
|
|
res=strchr(channel, chan);
|
|
if (res!=NULL) { fld=res-channel+1; } else { fld=1; }
|
|
if (fld>maxfld) maxfld=fld;
|
|
retstat=-1; /* errors in following section are not severe */
|
|
if (LscEqPar(crv, head)) { /* header matches: select sensor type and curve */
|
|
sprintf(buf, "INTYPE %c:%s;INCRV %c:%d;DISPFLD %d:%c,1;DISPLAY:%d"
|
|
, chan, intype, chan, num, fld, chan, maxfld);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
logfileOut("curve %d on channel %c selected\n", num, chan);
|
|
} else { /* header does not match -> download */
|
|
if (busy) ERR_MSG("busy");
|
|
logfileOut("download curve %d\n", num);
|
|
sprintf(buf, "INTYPE %c:%s;DISPFLD %d:%c,3;DISPLAY:%d"
|
|
, chan, intype, fld, chan, maxfld); /* select sensor type first to display sensor units */
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
sprintf(buf, "CRVDEL %d;CRVHDR?%d", num, num);
|
|
n=3;
|
|
do {
|
|
ERR_P(res=SerCmd(ser, buf));
|
|
res[4]='\0';
|
|
i=strcmp(res, "User");
|
|
n--;
|
|
} while (i!=0 && n!=0);
|
|
if (i!=0) ERR_MSG("can not delete curve");
|
|
do { /* download curve */
|
|
t=str_split1(points, '\n');
|
|
if (*points!='\0') ERR_I(LscCmdChk(ser, points));
|
|
points=t;
|
|
} while (t!=NULL);
|
|
sprintf(buf, "CRVHDR %d:%s;INCRV %c:%d;DISPFLD %d:%c,1", num, crv, chan, num, fld, chan); /* write header, select curve */
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
logfileOut("curve selected on channel %c\n", chan);
|
|
str_copy(head, crv);
|
|
str_upcase(head);
|
|
saveIt=1;
|
|
}
|
|
free(crv); crv=NULL;
|
|
|
|
/* 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 (manualX) ERR_SI(fputs(deviceX, fil));
|
|
ERR_SI(fputs("/", fil));
|
|
if (manualP) ERR_SI(fputs(deviceP, fil));
|
|
ERR_SI(fputs("\n", fil));
|
|
sprintf(buf, "%d:%s", num, head);
|
|
ERR_SI(fputs(buf, fil)); /* write actual entry */
|
|
if (start!=s) { /* write content before replaced entry */
|
|
ERR_SI(fputs("\n", fil));
|
|
ERR_SI(fputs(start, fil));
|
|
}
|
|
if (e!=NULL) { /* write content after replaced entry */
|
|
ERR_SI(fputs("\n", fil));
|
|
ERR_SI(fputs(e, fil));
|
|
}
|
|
ERR_SI(fclose(fil));
|
|
fil=NULL;
|
|
free(cache);
|
|
/* re-read it */
|
|
ERR_P(cache=str_read_arg(nbuf, NULL, 0));
|
|
return(0);
|
|
|
|
OnError:
|
|
if (crv!=NULL) free(crv);
|
|
if (fil!=NULL) fclose(fil);
|
|
return(retstat);
|
|
}
|
|
|
|
int configInput(int sampleStick) {
|
|
char *t;
|
|
char buf[80], nam[16], nbuf[256];
|
|
int i, j, n, nn;
|
|
int retstat;
|
|
|
|
retstat=-2; /* errors in following section are severe */
|
|
if (sampleStick) {
|
|
if (manualP) {
|
|
sprintf(buf, ".%s.", deviceP);
|
|
} else {
|
|
sprintf(buf, "%+d ", codP);
|
|
if (codP==0) return(0);
|
|
}
|
|
} else {
|
|
if (manualX) {
|
|
sprintf(buf, ".%s.", deviceX);
|
|
} else {
|
|
sprintf(buf, "%+d ", codX);
|
|
if (codX==0) return(0);
|
|
}
|
|
}
|
|
if (table!=NULL && tim>tableTime+60) { free(table); table=NULL; }; /* clear old table */
|
|
if (table==NULL) { /* read table */
|
|
str_copy(nbuf, binDir);
|
|
str_append(nbuf, TABLE_FILE);
|
|
ERR_P(table=str_read_arg(nbuf, NULL, 0));
|
|
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 (sampleStick) {
|
|
nP=0;
|
|
i=sscanf(t, "%12s%d%d", nam, &nn, &n);
|
|
if (i<1) ERR_MSG("missing sensor name");
|
|
j=1;
|
|
if (n<0 || n>2) ERR_MSG("illegal value for nsensor");
|
|
if (n==0) return(0);
|
|
if (!manualP) { /* set device name */
|
|
str_copy(deviceP, nam);
|
|
deviceP[strlen(deviceP)-1]='\0'; /* strip off '.' */
|
|
concatDevice();
|
|
}
|
|
str_append(nam,"s");
|
|
} else {
|
|
nX=0;
|
|
tLow=0; tHigh=0;
|
|
controlMode=0;
|
|
i=sscanf(t, "%12s%d%d%d%f%f%f%f%f", nam, &n, &nn, &controlMode, &tLimit, &resist, &power, &tLow, &tHigh);
|
|
if (i<7) ERR_MSG("missing some sensor parameters");
|
|
j=0;
|
|
if (n<0 || n>2) ERR_MSG("illegal value for nsensor");
|
|
if (n==0) return(0);
|
|
if (!manualX) { /* set device name */
|
|
str_copy(deviceX, nam);
|
|
deviceX[strlen(deviceX)-1]='\0'; /* strip off '.' */
|
|
concatDevice();
|
|
}
|
|
str_append(nam, "x");
|
|
}
|
|
ERR_I(retstat=instCurve(nam, channel[j]));
|
|
if (n==2) {
|
|
str_append(nam, "l");
|
|
ERR_I(retstat=instCurve(nam, channel[j+2]));
|
|
}
|
|
if (sampleStick) {
|
|
nP=n;
|
|
} else {
|
|
nX=n;
|
|
}
|
|
return(0);
|
|
OnError: return(retstat);
|
|
}
|
|
|
|
int loadCache() {
|
|
int i, j;
|
|
char *res, *p;
|
|
char buf[256], nbuf[256], lbuf[16];
|
|
FILE *fil;
|
|
|
|
fil=NULL;
|
|
sprintf(lbuf, "lsc.%d", serialNo);
|
|
str_copy(nbuf, logDir);
|
|
str_append(nbuf, lbuf);
|
|
ERR_SP(fil=fopen(nbuf, "w"));
|
|
if (manualX) ERR_SI(fputs(deviceX, fil));
|
|
ERR_SI(fputs("/", fil));
|
|
if (manualP) ERR_SI(fputs(deviceP, fil));
|
|
ERR_SI(fputs("\n", fil));
|
|
for (i=60; i>21; i-=4) {
|
|
sprintf(buf, "CRVHDR?%d;CRVHDR?%d;CRVHDR?%d;CRVHDR?%d", i, i-1, i-2, i-3);
|
|
ERR_P(res=SerCmd(ser, buf));
|
|
for (j=i; j>i-4; j--) {
|
|
p=str_split1(res, ';');
|
|
if (res[1]=='s') { i=0; break;} /* s of "User", must be empty slot, lowercase letters are not programmable */
|
|
sprintf(buf, "%d:%s", j, res);
|
|
ERR_SI(fputs(buf, fil));
|
|
ERR_SI(fputs("\n", fil));
|
|
if (p==NULL) break;
|
|
res=p;
|
|
}
|
|
}
|
|
ERR_SI(fclose(fil));
|
|
/* re-read cache */
|
|
ERR_P(cache=str_read_arg(nbuf, NULL, 0));
|
|
return(0);
|
|
OnError:
|
|
if (fil!=NULL) fclose(fil);
|
|
return(-1);
|
|
}
|
|
|
|
float WeightedAverage(int n, float t1, float t2) {
|
|
float p,q;
|
|
if (n==0) {
|
|
return(0.0);
|
|
} else if (n<2) {
|
|
return(t1);
|
|
} else {
|
|
if (t2<tLow) {
|
|
return(t2);
|
|
} else if (t1<tHigh) {
|
|
p=tHigh-t1;
|
|
q=t2-tLow;
|
|
return((t1*p*p+t2*q*q)/(p*p+q*q));
|
|
} else {
|
|
return(t1);
|
|
}
|
|
}
|
|
}
|
|
|
|
int SetTemp(int switchOn) {
|
|
char buf[32];
|
|
char ch;
|
|
|
|
ch=channel[0];
|
|
if (nX>1 && tempC<(tLow+tHigh)/2) ch=channel[2];
|
|
if (nP>0) {
|
|
if (controlMode==1) { /* control directly on sample sensor */
|
|
tShift=0;
|
|
ch=channel[1];
|
|
if (nX>1 && tempC<(tLow+tHigh)/2) ch=channel[3];
|
|
} else if (controlMode!=2) {
|
|
tShift=0;
|
|
}
|
|
} else {
|
|
tShift=0;
|
|
}
|
|
tempH=tempC+tShift;
|
|
if (switchOn) {
|
|
sprintf(buf, "CSET 1:%c,1;RANGE:5;SETP 1:%f", ch, tempH);
|
|
} else {
|
|
sprintf(buf, "CSET 1:%c,1;SETP 1:%f", ch, tempH);
|
|
}
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int ReadTemp() {
|
|
char buf[256], lbuf[16];
|
|
char *res;
|
|
int i, key, k;
|
|
int cod1, cod2, out1, out2; /* codes read from digital input/output */
|
|
int codX1, codP1;
|
|
float t2[2], t4[4], p, d;
|
|
|
|
ERR_P(res=SerCmdC(ser, "DIOST?;HTR?;BUSY?;DOUT 3,29"));
|
|
if (0==strcmp(res, "?TMO")) {
|
|
if (0==noResp) logfileOut("no response\n");
|
|
noResp=1;
|
|
return(0);
|
|
}
|
|
i=sscanf(res, "%d%*c%d%*c%f%*c%d", &cod1, &out1, &htr, &busy);
|
|
if (i!=4) ERR_MSG("bad answer 0");
|
|
|
|
if (noResp) { /* check serial number */
|
|
ERR_P(res=SerCmdC(ser, "*IDN?"));
|
|
if (0!=strncmp(res, "LSCI,MODEL340,", 14)) return(0);
|
|
res+=14;
|
|
k=0;
|
|
sscanf(res, "%d", &k);
|
|
if (k!=0 && k!=serialNo) {
|
|
serialNo=k;
|
|
dirtyX=1; dirtyP=1;
|
|
ERR_I(LscCmdChkC(ser, "RANGE:0")); /* switch off heater */
|
|
/* reload curve cache: */
|
|
if (cache!=NULL) free(cache);
|
|
sprintf(lbuf, "lsc.%d", serialNo);
|
|
str_copy(buf, logDir);
|
|
str_append(buf, lbuf);
|
|
cache=str_read_arg(buf, NULL, 0);
|
|
if (cache==NULL && 0==strcmp(ErrMessage, "file not found")) ERR_I(loadCache());
|
|
deviceX[0]='\0';
|
|
deviceP[0]='\0';
|
|
sscanf(cache, "%15[^/!]%*c%15[^\n!]", deviceX, deviceP); /* read device names separated by '/' */
|
|
if (deviceX[0]!='\0') manualX=1;
|
|
if (deviceP[0]!='\0') manualP=1;
|
|
concatDevice();
|
|
}
|
|
noResp=0;
|
|
}
|
|
|
|
sprintf(buf, "KRDG?%c;KRDG?%c;KRDG?%c;KRDG?%c", channel[0], channel[1], channel[2], channel[3]);
|
|
ERR_P(res=SerCmd(ser, buf));
|
|
i=sscanf(res, "%f%*c%f%*c%f%*c%f", &t4[0], &t4[1], &t4[2], &t4[3]);
|
|
if (i!=4) ERR_MSG("bad answer 1");
|
|
tempX=WeightedAverage(nX, t4[0], t4[2]);
|
|
tempP=WeightedAverage(nP, t4[1], t4[3]);
|
|
if (tempP==0.0) tempP=tempX;
|
|
if (dirtyX==0 && dirtyP==0 && noResp==0 && tim>logTime) {
|
|
t2[0]=tempX;
|
|
t2[1]=tempP;
|
|
DlogPut(&dset, tim, 2, t2); DlogUpd(&dset);
|
|
logTime=(tim/logPeriod+1)*logPeriod;
|
|
}
|
|
if (nP>0 && nX>0 && controlMode==2) {
|
|
d=tempH-tempX; d=exp(-d*d); /* if d is small, we are far from setpoint */
|
|
if (tInt<60000/period) tInt+=d; /* increase integral time until 60 sec. */
|
|
p=d/tInt;
|
|
tShift=tShift*(1.0-p)+p*(tempX-tempP);
|
|
ERR_I(SetTemp(0));
|
|
}
|
|
|
|
ERR_P(res=SerCmdC(ser, "KEYST?;DIOST?;DOUT 3,30"));
|
|
i=sscanf(res, "%d%*c%d%*c%d", &key, &cod2, &out2);
|
|
if (i!=3) ERR_MSG("bad answer 2");
|
|
|
|
if (busy==0) {
|
|
|
|
while (out1!=30) {
|
|
ERR_I(LscCmdChkC(ser, "DOUT:3,30"));
|
|
ERR_P(res=SerCmdC(ser, "DIOST?"));
|
|
i=sscanf(res, "%d%*c%d", &cod1, &out1);
|
|
}
|
|
while (out2!=29) {
|
|
ERR_I(LscCmdChkC(ser, "DOUT:3,29"));
|
|
ERR_P(res=SerCmdC(ser, "DIOST?;DOUT 3,30"));
|
|
i=sscanf(res, "%d%*c%d", &cod2, &out2);
|
|
}
|
|
|
|
/* code conversion */
|
|
codX1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */
|
|
codP1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]);
|
|
if (codX<0) { codX=codX1; codP=codP1; } /* first time after restart */
|
|
if (codP1!=codP) {
|
|
dirtyP=1;
|
|
codP=codP1; manualP=0;
|
|
}
|
|
if (codX1!=codX) {
|
|
dirtyX=1;
|
|
codX=codX1; manualX=0;
|
|
}
|
|
}
|
|
|
|
if (key!=0) {
|
|
auto_remote_time=tim+600;
|
|
if (!(dirtyX || dirtyP)) {
|
|
logfileOut("user touched keys\n");
|
|
}
|
|
dirtyX=1; dirtyP=1;
|
|
ERR_P(res=SerCmdC(ser, "MODE?"));
|
|
mode=0;
|
|
sscanf(res, "%d", &mode);
|
|
if (mode==2) auto_remote_time=tim; /* user switched to remote mode */
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int Settings() {
|
|
char buf[256];
|
|
char *res;
|
|
int i, j, k, ia, ir;
|
|
float pa, pr, pw, dif;
|
|
|
|
if (dirtyX || dirtyP) {
|
|
if (busy==0 || dirtyX>=0 && dirtyP>=0) { /* do not enter when busy and dirtyX/P indicates error on last time */
|
|
if (device[0]=='\0') {
|
|
logfileOut("configure inputs for codes %d %d\n", codX, codP);
|
|
} else {
|
|
logfileOut("configure inputs for %s\n", device);
|
|
}
|
|
if (dirtyP) {
|
|
sprintf(buf, "DISPFLD 2:%c,1;DISPFLD 4:%c,1", channel[1], channel[3]);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
}
|
|
if (dirtyX) {
|
|
if (dirtyX>0) tryX=0;
|
|
sprintf(buf, "DISPFLD 1:%c,1;DISPFLD 3:%c,1", channel[0], channel[2]);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
nX=0;
|
|
if (!manualX) { deviceX[0]='\0'; concatDevice(); }
|
|
dirtyX=configInput(0);
|
|
if (dirtyX<0) {
|
|
tryX++;
|
|
if (dirtyX!=-1 || tryX>3) {
|
|
logfileShowErr("fatal error X");
|
|
dirtyX=0; deviceX[0]='\0'; concatDevice();
|
|
} else {
|
|
logfileShowErr("try again X");
|
|
}
|
|
} else {
|
|
/* control settings */
|
|
sprintf(buf, "CDISP 1:1,%d,1;MOUT 1:0;CMODE 1:1", (int)(resist+0.5));
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
ia=1; ir=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; ia=i; ir=j; }
|
|
} else {
|
|
if (power/pr<dif) { dif=power/pr; pw=pr; ia=i; ir=j; }
|
|
}
|
|
pr=pr/10;
|
|
}
|
|
pa=pa/4;
|
|
}
|
|
}
|
|
power=pw;
|
|
sprintf(buf, "CLIMIT 1:%f,0,0,%d,%d;CSET 1:%c,1,1,0", tLimit, ia, ir, channel[0]);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
sprintf(buf, "ALARM %c:%d,1,%f,0,0,1;ALARM %c:0;RELAY 1:1;BEEP:0"
|
|
, channel[0], (nX>0), tLimit, channel[2]);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
}
|
|
}
|
|
if (dirtyP) {
|
|
if (dirtyP>0) tryP=0;
|
|
nP=0;
|
|
if (!manualP) { deviceP[0]='\0'; concatDevice(); }
|
|
dirtyP=configInput(1);
|
|
if (dirtyP<0) {
|
|
tryP++;
|
|
if (dirtyP!=-1 || tryP>3) {
|
|
logfileShowErr("fatal error P");
|
|
dirtyP=0; deviceP[0]='\0'; concatDevice();
|
|
} else {
|
|
logfileShowErr("try again P");
|
|
}
|
|
} else {
|
|
sprintf(buf, "ALARM %c:%d,1,%f,0,0,1;ALARM %c:0;RELAY 1:1;BEEP:0"
|
|
, channel[1], (nP>0), tLimit, channel[3]);
|
|
ERR_I(LscCmdChk(ser, buf));
|
|
}
|
|
}
|
|
if (nP>=nX) {
|
|
maxfld=2*nP;
|
|
} else {
|
|
maxfld=2*nX-1;
|
|
}
|
|
if (maxfld>0) {
|
|
sprintf(buf, "MODE:2;DISPLAY:%d", maxfld);
|
|
} else {
|
|
maxfld=1;
|
|
sprintf(buf, "MODE:2;DISPLAY:1;DISPFLD 1:A,3", maxfld);
|
|
}
|
|
ERR_I(LscCmdChkC(ser, buf));
|
|
mode=2;
|
|
|
|
if (saveIt) {
|
|
ERR_P(res=SerCmdC(ser, "CRVSAV;BUSY?"));
|
|
do {
|
|
idleHdl(200, 0); /* wait 200 ms */
|
|
ERR_P(res=SerCmdC(ser, "BUSY?"));
|
|
sscanf(res, "%d", &busy);
|
|
} while (!busy);
|
|
saveIt=0;
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int ExecuteRequest() {
|
|
char *res, *t;
|
|
int iRet;
|
|
struct CocClient *client;
|
|
|
|
if (tim>auto_remote_time || setFlag) ERR_I(Settings());
|
|
if (setFlag) {
|
|
if (nX>0) {
|
|
tInt=0; /* reset integral time */
|
|
ERR_I(SetTemp(1));
|
|
logfileOut("set point\n");
|
|
} else {
|
|
logfileOut("flag reset\n");
|
|
}
|
|
setFlag=0;
|
|
}
|
|
client=CocGetNextCmd();
|
|
if (client!=NULL) {
|
|
if (NULL==strchr(client->cmd, ':')) {
|
|
res=SerCmdC(ser, client->cmd);
|
|
if (res==NULL) {
|
|
res=ErrMessage;
|
|
if (res==NULL) res="empty error message";
|
|
}
|
|
str_copy(client->res, res);
|
|
} else {
|
|
iRet=LscCmdChkC(ser, client->cmd);
|
|
if (iRet<0 && ErrMessage!=NULL) {
|
|
str_copy(client->res, ErrMessage);
|
|
} else {
|
|
str_copy(client->res, "o.k.");
|
|
}
|
|
}
|
|
client->cmd[0]='\0';
|
|
}
|
|
if (deviceFlag) {
|
|
t=strchr(device, '/');
|
|
if (t==NULL) {
|
|
str_copy(deviceX, device);
|
|
str_copy(deviceP, device);
|
|
manualX=1; dirtyX=1;
|
|
manualP=1; dirtyP=1;
|
|
} else {
|
|
if (t!=device) {
|
|
*t='\0';
|
|
str_copy(deviceX, device);
|
|
*t='/';
|
|
manualX=1; dirtyX=1;
|
|
}
|
|
t++;
|
|
if (*t!='\0') {
|
|
str_copy(deviceP, t);
|
|
manualP=1; dirtyP=1;
|
|
}
|
|
}
|
|
concatDevice();
|
|
deviceFlag=0;
|
|
}
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{ int logIt=0;
|
|
struct timeb tim1, tim0;
|
|
int i, tdif, iret;
|
|
char *host;
|
|
char buf[256], opt;
|
|
int port, msecTmo;
|
|
|
|
binDir="";
|
|
logDir="";
|
|
serverId="tecs";
|
|
host="lnsp26";
|
|
port=0;
|
|
msecTmo=0;
|
|
logfileOutTmp("%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;
|
|
period=5000;
|
|
opt=' ';
|
|
} else if ('s'==opt) {
|
|
logfileStd=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 {
|
|
logfileOutTmp("?");
|
|
}
|
|
if (opt!=' ') logfileOutTmp("-%c ", opt);
|
|
logfileOutTmp("%s ", argv[i]);
|
|
}
|
|
}
|
|
if (port==0) port=9753;
|
|
if (msecTmo==0) msecTmo=4000;
|
|
|
|
str_copy(buf, logDir);
|
|
str_append(buf, serverId);
|
|
|
|
logfileInit(buf, logIt);
|
|
logfileOutTmp("\n");
|
|
logfileWriteTmp();
|
|
|
|
ERR_I(CocInitServer(1024, port));
|
|
|
|
CocDefFlt(tempX, CocRD);
|
|
CocDefFlt(tempP, CocRD);
|
|
CocDefFlt(htr, CocRD);
|
|
CocDefFlt(tempC, setFlag);
|
|
CocDefStr(device, deviceFlag);
|
|
CocDefInt(controlMode, CocWR);
|
|
CocDefInt(quit, CocWR);
|
|
|
|
ERR_P(ser=SerOpen(host, logIt, msecTmo, idleHdl));
|
|
ERR_I(CocHandleRequests(100, 0));
|
|
ftime(&tim0);
|
|
str_copy(buf, logDir);
|
|
str_append(buf, serverId);
|
|
str_append(buf, ".dlog");
|
|
iret=DlogOpen(&dset, buf, 1);
|
|
if (iret<0) {
|
|
ERR_I(DlogCreate(&dset, buf, tim0.time, 2, 24*60*60/logPeriod, logPeriod, 0.0));
|
|
}
|
|
while (!quit) {
|
|
logfileStamp("");
|
|
if (logIt) {
|
|
logfileWriteTmp();
|
|
} else {
|
|
logfilePurge();
|
|
}
|
|
/* read & control temp */
|
|
iret=ReadTemp();
|
|
if (iret<0) logfileShowErr("ReadTemp");
|
|
if (tim>=auto_remote_time) {
|
|
iret=Settings();
|
|
if (iret<0) logfileShowErr("Settings");
|
|
}
|
|
|
|
while (!quit) {
|
|
ftime(&tim1);
|
|
tdif=period-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
|
|
if (tdif<0) { tim=tim1.time; break; } /* timeout */
|
|
iret=CocHandleRequests(tdif, 0);
|
|
if (iret!=2) { time(&tim); break; } /* timeout */
|
|
if (iret<0) logfileShowErr("CocHandleRequests");
|
|
tim=tim1.time;
|
|
iret=ExecuteRequest();
|
|
if (iret<0) logfileShowErr("ExecuteRequest");
|
|
}
|
|
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("%d cycles lost\n", tdif-1);
|
|
}
|
|
}
|
|
logfileOut("%s got quit command\n", serverId);
|
|
DlogClose(&dset);
|
|
return(1);
|
|
OnError:
|
|
SerClose(ser);
|
|
CocCloseServer();
|
|
ERR_EXIT("TECS");
|
|
}
|