#include #include #include #include #include #include #include "logger.h" #include "sics.h" #define LOGGER_NAN -999999. #define ONE_YEAR (366*24*3600) #define LLEN 1024 typedef enum { NUMERIC, TEXT } CompType; typedef struct { SConnection *pCon; char *var; 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]; */ int np; char *none; } Compressor; static char *dir = NULL; 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; } static void OutString(Compressor *c, time_t t, char *str) { char line[LLEN]; /* 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)); } } else { snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y); } /* printf("-%s\n", line); */ c->tlast = t; SCWrite(c->pCon, line, eWarning); c->np--; } } static void PutValue(Compressor *c, time_t t, char *value) { char *p; double y; if (c->var) { SCPrintf(c->pCon, eWarning, "*%s exact %d\n", c->var, c->exact); c->var = NULL; } if (c->type == NUMERIC) { if (t == 0) { /* finish */ t = c->tlim + 3 * c->step; y = 0; } else { y = strtod(value, &p); if (p == value) { y = LOGGER_NAN; } else { if (y == LOGGER_NAN) y *= 1.0000002; } } /* printf("put %ld %g\n", t, y); */ if (c->tlim == 0) goto first; if (t >= c->tlim) { 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); } goto first; } } 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; } else if (c->type == TEXT) { if (t != 0) OutString(c, t, value); } } /*--------------------------------------------------------------------------*/ static long getOpt(char *line, int *isdst, int *exact) { long lxs; char *opt; opt = strstr(line, "isdst"); if (opt) { sscanf(opt, "isdst %d", isdst); } opt = strstr(line, "exact"); if (opt) { sscanf(opt, "exact %d", exact); } opt = strstr(line, "period"); if (opt) { sscanf(opt, "period %ld", &lxs); return lxs; } else { return -1; } } /*--------------------------------------------------------------------------*/ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { time_t from, to, step, xs, lastt, now; long lxs; char *p; int i, iarg, l, iret, loss, np; int inRange; int yday=0; time_t t, startim; struct tm tm; char stim[32], path[LLEN], line[LLEN], lastval[LLEN]; char *lin, *val, *stp; FILE *fil; Compressor c={0}; float yy, lasty; CompType type0; DIR *dr; char *opt; int isdst; int overflow; /* argtolower(argc, argv); */ if (argc < 4) goto illarg; now = time(NULL); from = strtol(argv[1], &p, 0); /* unix time, not year 2038 safe */ if (p == argv[1]) goto illarg; to = strtol(argv[2], &p, 0); if (p == argv[2]) goto illarg; if (from < ONE_YEAR) { from += now; } if (to < ONE_YEAR) { to += now; } iarg = 3; while (1) { if (iarg>=argc) goto illarg; if (strcasecmp(argv[iarg],"text") == 0) { /* non-numeric values */ iarg++; step = 1; type0 = TEXT; np = from - to + 2; break; } else if (strcasecmp(argv[iarg],"none") == 0) { /* none */ iarg++; if (iarg >= argc) goto illarg; c.none = argv[iarg]; iarg++; } else if (strcasecmp(argv[iarg],"np") == 0) { /* max. number of points */ iarg++; if (iarg >= argc) goto illarg; type0 = NUMERIC; np = strtol(argv[iarg], &p, 0); if (p == argv[iarg]) goto illarg; iarg++; if (to <= from) { step = 1; } else if (np <= 2) { step = to - from; } else { step = (to - from) / (np - 2) + 1; } break; } else { step = strtol(argv[iarg], &p, 0); if (p == argv[iarg]) goto illarg; iarg++; if (step <= 0) step = 1; type0 = NUMERIC; np = (from - to) / step + 2; } } if (step <= 0) step = 1; snprintf(line, sizeof line, "%ld\n", (long)now); SCWrite(pCon, line, eWarning); if (dir == NULL) { dir = IFindOption(pSICSOptions, "LoggerDir"); if (dir == NULL) { SCWrite(pCon, "LoggerDir not found", eError); return 0; } LoggerSetDir(dir); } if (dir2 == NULL) { dir2 = IFindOption(pSICSOptions, "LoggerDir2"); if (dir2 == NULL) dir2=""; } loss = 0; overflow = 0; for (i=iarg; i= 0) { if (lxs == 0) { c.type = TEXT; } else { c.type = type0; xs = lxs; } if (xs < step) { loss = 1; xs = step; } } } } } if (fil == NULL) { lin = NULL; } else { do { lin = fgets(line, sizeof line, fil); /* printf("%s\n", line); */ if (lin == NULL) break; if (line[0] == '#') { lxs = getOpt(line, &isdst, &c.exact); if (lxs >= 0) { if (lxs == 0) { c.type = TEXT; } else { c.type = type0; xs = lxs; } if (xs < step) { loss = 1; xs = step; } } lin[0]='\0'; } else { p = strchr(line, '\n'); if (p) *p='\0'; p = strchr(line, '#'); if (p) *p='\0'; } } while (lin[0] == '\0'); } if (lin != NULL) { /* printf(" %s\n", line); */ p = strchr(line, '\t'); if (p) { *p='\0'; val = p+1; } else { val = ""; } p = strchr(val, '\t'); if (p) { stp = p+1; *p='\0'; iret = sscanf(stp, "%ld", &lxs); if (iret == 1) { if (lxs == 0) { c.type = TEXT; } else { c.type = type0; xs = lxs; } if (xs < step) { loss = 1; xs = step; } } } iret = sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec); if (iret != 3) { lin = NULL; } else { tm.tm_isdst = isdst; t=mktime(&tm); if (!inRange) { if (t < startim) { lastval[0]='\0'; strncat(lastval, val, sizeof lastval - 1); lastt = t; } else { inRange=1; if (lastt != 0) { PutValue(&c, lastt, lastval); } PutValue(&c, t, val); } } else { PutValue(&c, t, val); } } } if (lin == NULL) { tm.tm_hour = 24; /* try next day */ tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; startim=mktime(&tm); continue; } } if (!inRange) { if (lastt != 0) { PutValue(&c, lastt, lastval); } } c.ylast = LOGGER_NAN; /* force output of last value */ PutValue(&c, 0, ""); /* finish */ if (fil) { fclose(fil); fil = NULL; } if (c.np < 0) overflow = 1; } snprintf(line, sizeof line, "*%d %d\n", loss, overflow); SCWrite(pCon, line, eWarning); return 1; illarg: SCWrite(pCon, "illegal argument(s)", eError); return 0; } /*--------------------------------------------------------------------------*/ static void KillLogReader(void *data) { Logger *p, *next; KillDummy(data); LoggerFreeAll(); } /*--------------------------------------------------------------------------*/ void LogReaderInit(void) { AddCommand(pServ->pSics,"Graph",LogReader,KillLogReader,NULL); }