- added FindCommandDescriptor to SCinter.*
- modified support for dynamic objects - improved logger system - various fixes
This commit is contained in:
259
logreader.c
259
logreader.c
@ -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;
|
||||
|
Reference in New Issue
Block a user