- added FindCommandDescriptor to SCinter.*

- modified support for dynamic objects
- improved logger system
- various fixes
This commit is contained in:
zolliker
2008-03-03 14:49:15 +00:00
parent 33c0b7dcaa
commit a529bda307
13 changed files with 337 additions and 285 deletions

View File

@ -4,6 +4,7 @@
#include <fortify.h>
#include <errno.h>
#include <dirent.h>
#include <math.h>
#include "logger.h"
#include "sics.h"
@ -13,19 +14,26 @@
typedef enum { NUMERIC, TEXT } CompType;
typedef struct {
time_t t;
float y;
} Point;
typedef struct {
SConnection *pCon;
char var[1024];
int exact;
CompType type;
time_t step;
time_t tlim;
time_t tmin, tmax, tlast, told;
float ymin, ymax, ylast, yold;
char slast[LLEN];
/* char set[LLEN]; */
time_t tlim; /* 0: initial state */
Point best; /* best point, to be written if tlim > 0 */
Point written; /* last written point */
Point last; /* last point */
char buf[LLEN];
int np;
char *none;
char *header;
time_t period;
int omitEqual;
} Compressor;
static char *dir = NULL;
@ -34,112 +42,103 @@ static char *dir2 = NULL;
static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) {
c->pCon = pCon;
c->step = step;
c->tmin = -2;
c->tmax = 0;
c->tlast = 0;
c->tlim = 0;
c->told = 0;
c->slast[0]='\0';
c->ylast = LOGGER_NAN;
c->last.y = LOGGER_NAN;
c->last.t = 0;
c->buf[0]='\0';
c->written.t = 0;
c->written.y = LOGGER_NAN;
c->omitEqual = 1;
}
static void OutString(Compressor *c, time_t t, char *str) {
char line[LLEN];
static void OutFloat(Compressor *c, Point p) {
char *value;
/* printf("out %ld %g\n", t, y); */
if (0 != strcmp(str, c->slast)) {
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), str);
c->tlast = t;
c->slast[0]='\0';
strncat(c->slast, str, sizeof c->slast - 1);
SCWrite(c->pCon, line, eWarning);
c->np--;
}
}
static void OutFloat(Compressor *c, time_t t, float y) {
char line[80];
/* printf("out %ld %g\n", t, y); */
if (y != c->ylast || (!c->exact && t != c->tlast)) {
c->ylast = y;
if (y == LOGGER_NAN) {
if (c->none) {
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), c->none);
} else {
snprintf(line, sizeof line, "%ld\n", (long)(t - c->tlast));
}
if (p.y == LOGGER_NAN) {
if (c->omitEqual && c->written.y == LOGGER_NAN) return;
if (c->none) {
value = c->none;
} else {
snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y);
value = "";
}
/* printf("-%s\n", line); */
c->tlast = t;
SCWrite(c->pCon, line, eWarning);
c->np--;
} else {
if (c->omitEqual && c->written.y == p.y) return;
snprintf(c->buf, sizeof(c->buf), "%g", p.y);
value = c->buf;
}
SCPrintf(c->pCon, eWarning, "%ld %s", (long)(p.t - c->written.t), value);
c->written = p;
c->np--;
}
static void WriteHeader(Compressor *c) {
if (c->header) {
SCPrintf(c->pCon, eWarning, "*%s period %ld\n", c->header, c->period);
c->header = NULL;
}
}
static void PutValue(Compressor *c, time_t t, char *value) {
char *p;
double y;
if (c->var[0]) {
SCPrintf(c->pCon, eWarning, "*%s exact %d\n", c->var, c->exact);
c->var[0] = 0;
}
Point new;
WriteHeader(c);
if (c->type == NUMERIC) {
if (t == 0) { /* finish */
t = c->tlim + 3 * c->step;
y = 0;
new.y = strtod(value, &p);
if (p == value) {
new.y = LOGGER_NAN;
} else {
y = strtod(value, &p);
if (p == value) {
y = LOGGER_NAN;
} else {
if (y == LOGGER_NAN) y *= 1.0000002;
}
if (new.y == LOGGER_NAN) new.y *= 1.0000002;
}
/* printf("put %ld %g\n", t, y); */
if (c->tlim == 0) goto first;
if (t >= c->tlim) {
new.t = t;
if (t >= c->tlim) { /* a new interval starts */
if (c->tlim == 0) {
c->tlim = t;
} else if (c->best.y != c->written.y) {
OutFloat(c, c->best);
}
c->best = new;
c->tlim += c->step;
if (c->tmin > c->tmax) {
OutFloat(c, c->tmax, c->ymax);
c->ymax = c->ymin;
c->tmax = c->tmin;
} else {
OutFloat(c, c->tmin, c->ymin);
if (c->tmin == c->tmax) goto first;
c->ymin = c->ymax;
c->tmin = c->tmax;
}
if (t >= c->tlim) {
OutFloat(c, c->tmin, c->ymin);
if (t >= c->tlim + c->step) {
OutFloat(c, c->told, c->yold);
if (t > c->tlim) {
if (c->last.y != c->written.y) {
OutFloat(c, c->last);
}
goto first;
c->tlim = t + c->step;
}
} else { /* not the first point */
if (fabs(new.y - c->best.y) > fabs(c->written.y - c->best.y)) {
c->best = new;
}
}
if (y <= c->ymin) {
c->ymin = y;
c->tmin = t;
} else if (y > c->ymax) {
c->ymax = y;
c->tmax = t;
}
c->yold = y;
c->told = t;
return;
first:
c->tlim = t + 2 * c->step;
c->tmin = t;
c->tmax = t;
c->ymin = y;
c->ymax = y;
return;
c->last = new;
} else if (c->type == TEXT) {
if (t != 0) OutString(c, t, value);
if (0 != strncmp(value, c->buf, sizeof(c->buf)-1)) {
snprintf(c->buf, sizeof(c->buf), "%s", value);
SCPrintf(c->pCon, eWarning, "%ld %s\n", (long)(t - c->written.t), value);
c->written.t = t;
c->np--;
}
}
}
static void PutFinish(Compressor *c, time_t now) {
char value[32];
if (c->tlim != 0) { /* there is data already */
c->omitEqual = 0;
if (c->type == NUMERIC) {
if (now > c->last.t) { /* copy last value to the actual time */
if (c->last.y != LOGGER_NAN) {
snprintf(value, sizeof value, "%g", c->last.y);
PutValue(c, now, value);
}
if (c->best.t > c->written.t) {
OutFloat(c, c->best); /* write last buffered value */
}
}
} if (now > c->last.t) {
PutValue(c, now, c->buf);
}
}
}
/*--------------------------------------------------------------------------*/
@ -194,7 +193,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
First line: returning the actual time on the server (this time is used for relative times)
For each variable which has data in the given interval,
the variable name is returned preceeded by a '*', followed by some options* separated with
the variable name is returned preceeded by a '*', followed by some infos* separated with
blanks.
After the header line for every data point a line follows with
a time relative to the last point and the value.
@ -207,13 +206,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
<overflow> is 1, when overflow occured, 0 else. Overflow may happen only
when np is given and a text variable was demanded.
*actually only one option exists (you might ignore it):
exact <value>
<value> is 1 when the value is exact, i.e. an integer.
<value> is 0 else.
*actually only one info exists: period <value>. This is the update rate in seconds.
As equal values are not transmitted, two points (t1,y1) and (t2,y2) with a distance
(t2 - t1) > period should not be connected directly. The plot software should generate
an intermediate point at (t2-period,y1).
*/
time_t from, to, step, xs, lastt, now;
long lxs;
time_t from, to, step, xs, lastt;
char *p, *varp;
int i, j, iarg, l, iret, loss, np;
int inRange;
@ -230,6 +229,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
char *opt;
int isdst;
int overflow;
time_t now, now1, now2, nowi;
char var[256];
/* argtolower(argc, argv); */
if (argc < 4) goto illarg;
@ -293,12 +294,16 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
SCWrite(pCon, "ERROR: LoggerDir not found", eError);
return 0;
}
LoggerSetDir(dir);
}
if (dir2 == NULL) {
dir2 = IFindOption(pSICSOptions, "LoggerDir2");
if (dir2 == NULL) dir2="";
if (dir2 == NULL) {
dir2="";
}
}
now1 = LoggerGetLastLife(NULL);
if (now1 == 0) now1 = now;
now2 = 0;
loss = 0;
overflow = 0;
@ -312,23 +317,32 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
/* convert slashes to dots */
varp = argv[i];
if (*varp == '/') varp++;
for (j = 0; j < sizeof(c.var) && *varp != 0; j++, varp++) {
for (j = 0; j < sizeof(var)-1 && *varp != 0; j++, varp++) {
if (*varp == '/') {
c.var[j] = '.';
var[j] = '.';
} else {
c.var[j] = *varp;
var[j] = *varp;
}
}
c.header = argv[i];
c.period = 0;
var[j] = '\0';
c.type = type0;
c.np = np;
l = LoggerVarPath(dir, path, sizeof path, c.var);
l = LoggerVarPath(dir, path, sizeof path, var);
dr = opendir(path);
if (dr) {
nowi = now1;
closedir(dr);
} else {
l = LoggerVarPath(dir2, path, sizeof path, c.var);
if (now2 == 0) {
now2 = LoggerGetLastLife(dir2);
if (now2 == 0) now2 = now;
}
l = LoggerVarPath(dir2, path, sizeof path, var);
nowi = now2;
dr = opendir(path);
if (dr) {
closedir(dr);
@ -337,7 +351,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
isdst = -1;
fil = NULL;
while (startim <= to && c.tlast <= to) {
while (startim <= to && c.last.t <= to) {
tm = *localtime(&startim);
if (tm.tm_yday != yday) {
if (fil != NULL) { /* close file if day changed */
@ -356,13 +370,14 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
fclose(fil);
fil = NULL;
} else {
lxs = getOpt(line, &isdst, &c.exact);
if (lxs >= 0) {
if (lxs == 0) {
c.period = getOpt(line, &isdst, &c.exact);
/* if (c.exact) c.period = 0; */
if (c.period >= 0) {
if (c.period == 0) {
c.type = TEXT;
} else {
c.type = type0;
xs = lxs;
xs = c.period;
}
if (xs < step) {
loss = 1;
@ -380,13 +395,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
/* printf("%s\n", line); */
if (lin == NULL) break;
if (line[0] == '#') {
lxs = getOpt(line, &isdst, &c.exact);
if (lxs >= 0) {
if (lxs == 0) {
c.period = getOpt(line, &isdst, &c.exact);
if (c.period >= 0) {
if (c.period == 0) {
c.type = TEXT;
} else {
c.type = type0;
xs = lxs;
xs = c.period;
}
if (xs < step) {
loss = 1;
@ -413,13 +428,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
if (p) {
stp = p+1;
*p='\0';
iret = sscanf(stp, "%ld", &lxs);
iret = sscanf(stp, "%ld", &c.period);
if (iret == 1) {
if (lxs == 0) {
if (c.period == 0) {
c.type = TEXT;
} else {
c.type = type0;
xs = lxs;
xs = c.period;
}
if (xs < step) {
loss = 1;
@ -464,8 +479,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
PutValue(&c, lastt, lastval);
}
}
c.ylast = LOGGER_NAN; /* force output of last value */
PutValue(&c, 0, ""); /* finish */
WriteHeader(&c); /* write header, if not already done */
PutFinish(&c, nowi);
if (fil) {
fclose(fil);
fil = NULL;