249 |
249 |
250 |
250 |
251 int comp(ls_list **lsp1, ls_list **lsp2) |
251 int comp(ls_list **lsp1, ls_list **lsp2) |
252 { |
252 { |
253 return strcmp((*lsp1)->d_name, (*lsp2)->d_name); |
253 return strcmp((*lsp1)->d_name, (*lsp2)->d_name); |
254 } |
|
255 |
|
256 |
|
257 |
|
258 /* |
|
259 * ARCHIVE DIR |
|
260 * ARCHIVE GET filename |
|
261 * ARCHIVE LOG filename |
|
262 * ARCHIVE HELP |
|
263 */ |
|
264 int cmd_archive(char *buf) |
|
265 { |
|
266 char *opt, *param, *name = NULL, *filename = NULL, *logname = NULL, mbits[11], tstr[24]; |
|
267 DIR *dd; |
|
268 FILE *fp; |
|
269 struct dirent *result; |
|
270 ls_list *lsx = NULL, *tmp; |
|
271 struct stat sbuf; |
|
272 struct tm *tbuf; |
|
273 time_t ftime; |
|
274 int found; |
|
275 units_list *unit; |
|
276 |
|
277 |
|
278 opt = strtok(buf, " \0"); |
|
279 opt = strtok(NULL, " \0"); |
|
280 |
|
281 if (opt == NULL) { |
|
282 srv_send((char *)"501 Subcommand missing"); |
|
283 return 0; |
|
284 } |
|
285 param = strtok(NULL, "\0"); |
|
286 |
|
287 if (strcmp(opt, (char *)"HELP") == 0) { |
|
288 srv_send((char *)"100 Help text follows:"); |
|
289 srv_send((char *)"Recognized commands:"); |
|
290 srv_send((char *)"ARCHIVE DIR Archived logfiles directory"); |
|
291 srv_send((char *)"ARCHIVE GET filename Archived logfile download"); |
|
292 srv_send((char *)"ARCHIVE LOG filename Archived logfile data in graphsteps"); |
|
293 srv_send((char *)"."); |
|
294 return 0; |
|
295 } |
|
296 |
|
297 if (strcmp(opt, (char *)"DIR") == 0) { |
|
298 |
|
299 if (getenv((char *)"USER") == NULL) { |
|
300 name = xstrcpy((char *)"/root"); |
|
301 } else { |
|
302 name = xstrcpy(getenv((char *)"HOME")); |
|
303 } |
|
304 name = xstrcat(name, (char *)"/.thermferm/log/"); |
|
305 |
|
306 if ((dd = opendir(name))) { |
|
307 for (;;) { |
|
308 if (! (result = readdir(dd))) { |
|
309 syslog(LOG_NOTICE, "readdir: error=%d", errno); |
|
310 break; |
|
311 } |
|
312 if (result->d_name[0] != '.') { |
|
313 filename = xstrcpy(name); |
|
314 filename = xstrcat(filename, result->d_name); |
|
315 /* |
|
316 * Remove files from the list when they are in use |
|
317 */ |
|
318 found = 0; |
|
319 for (unit = Config.units; unit; unit = unit->next) { |
|
320 if (unit->mode != UNITMODE_OFF) { |
|
321 logname = xstrcpy(unit->product_code); |
|
322 logname = xstrcat(logname, (char *)" "); |
|
323 logname = xstrcat(logname, unit->product_name); |
|
324 logname = xstrcat(logname, (char *)".log"); |
|
325 if (! strcmp(result->d_name, logname)) |
|
326 found = 1; |
|
327 free(logname); |
|
328 logname = NULL; |
|
329 } |
|
330 } |
|
331 if ((found == 0) && ((stat(filename, &sbuf)) == 0)) { |
|
332 fill_list(&lsx, result->d_name, sbuf.st_mode, sbuf.st_size, sbuf.st_mtime); |
|
333 } |
|
334 free(filename); |
|
335 filename = NULL; |
|
336 } |
|
337 } |
|
338 closedir(dd); |
|
339 } else { |
|
340 syslog(LOG_NOTICE, "opendir: \"%s\" error=%d", name, errno); |
|
341 } |
|
342 |
|
343 sort_list(&lsx); |
|
344 |
|
345 srv_send((char *)"212 Archive directory follows:"); |
|
346 for (tmp = lsx; tmp; tmp = tmp->next) { |
|
347 sprintf(mbits, "----------"); |
|
348 if (tmp->mode & S_IRUSR) |
|
349 mbits[1] = 'r'; |
|
350 if (tmp->mode & S_IWUSR) |
|
351 mbits[2] = 'w'; |
|
352 if (tmp->mode & S_IXUSR) |
|
353 mbits[3] = 'x'; |
|
354 if (tmp->mode & S_IRGRP) |
|
355 mbits[4] = 'r'; |
|
356 if (tmp->mode & S_IWGRP) |
|
357 mbits[5] = 'w'; |
|
358 if (tmp->mode & S_IXGRP) |
|
359 mbits[6] = 'x'; |
|
360 if (tmp->mode & S_IROTH) |
|
361 mbits[7] = 'r'; |
|
362 if (tmp->mode & S_IWOTH) |
|
363 mbits[8] = 'w'; |
|
364 if (tmp->mode & S_IXOTH) |
|
365 mbits[9] = 'x'; |
|
366 ftime = tmp->mtime; |
|
367 tbuf = localtime(&ftime); |
|
368 sprintf(tstr, "%02d %s %04d %02d:%02d", tbuf->tm_mday, MONTH[tbuf->tm_mon], tbuf->tm_year+1900, tbuf->tm_hour, tbuf->tm_min); |
|
369 srv_send((char *)"%s,%s,%d,%s", tmp->d_name, mbits, tmp->size, tstr); |
|
370 } |
|
371 srv_send((char *)"."); |
|
372 tidy_lslist(&lsx); |
|
373 |
|
374 free(name); |
|
375 name = NULL; |
|
376 return 0; |
|
377 } |
|
378 |
|
379 if (param == NULL) { |
|
380 srv_send((char *)"502 Parameter missing"); |
|
381 return 0; |
|
382 } |
|
383 |
|
384 if (strcmp(opt, (char *)"GET") == 0) { |
|
385 if (getenv((char *)"USER") == NULL) { |
|
386 name = xstrcpy((char *)"/root"); |
|
387 } else { |
|
388 name = xstrcpy(getenv((char *)"HOME")); |
|
389 } |
|
390 name = xstrcat(name, (char *)"/.thermferm/log/"); |
|
391 name = xstrcat(name, param); |
|
392 |
|
393 if ((fp = fopen(name, "r"))) { |
|
394 char buffer[256]; |
|
395 |
|
396 srv_send((char *)"212 Archive file follows:"); |
|
397 while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { |
|
398 int i; |
|
399 |
|
400 for (i = 0; i < strlen(buffer); i++) { |
|
401 if (buffer[i] == '\n') |
|
402 buffer[i] = '\0'; |
|
403 if (buffer[i] == '\r') |
|
404 buffer[i] = '\0'; |
|
405 } |
|
406 srv_send(buffer); |
|
407 } |
|
408 srv_send((char *)"."); |
|
409 fclose(fp); |
|
410 } else { |
|
411 srv_send((char *)"440 No such file"); |
|
412 } |
|
413 |
|
414 free(name); |
|
415 name = NULL; |
|
416 return 0; |
|
417 } |
|
418 |
|
419 if (strcmp(opt, (char *)"LOG") == 0) { |
|
420 if (getenv((char *)"USER") == NULL) { |
|
421 name = xstrcpy((char *)"/root"); |
|
422 } else { |
|
423 name = xstrcpy(getenv((char *)"HOME")); |
|
424 } |
|
425 name = xstrcat(name, (char *)"/.thermferm/log/"); |
|
426 name = xstrcat(name, param); |
|
427 |
|
428 if ((fp = fopen(name, "r"))) { |
|
429 char buffer[256], outbuf[256], q[5], hr[3]; |
|
430 char *date_n, *mode_n, *air_n, *beer_n, *target_lo_n, *target_hi_n, *heater_n, *cooler_n, *room_n, *chiller_n; |
|
431 char *heater_u, *cooler_u; |
|
432 int lines = 0, heater_l = 0, cooler_l = 0, h = 0, c = 0, heat_used = 0, cool_used = 0, graphstep = 0; |
|
433 float room_t = 0.0; |
|
434 |
|
435 srv_send((char *)"212 Logfile list follows:"); |
|
436 while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { |
|
437 lines++; |
|
438 } |
|
439 fseek(fp, 0L, SEEK_SET); |
|
440 /* |
|
441 * We have counted the lines in the logfile including the header lines. |
|
442 * The header lines should be ignored but there are so few of them, we |
|
443 * just include them in the total. |
|
444 * Now find a reasonable interval of lines to sent to the client. |
|
445 */ |
|
446 for (graphstep = 1; graphstep <= MAX_INTERVALS; graphstep++) { |
|
447 if (lines < GRAPH_DATALINES[graphstep]) { |
|
448 break; |
|
449 } |
|
450 } |
|
451 if (graphstep > MAX_INTERVALS) |
|
452 graphstep = MAX_INTERVALS; |
|
453 syslog(LOG_NOTICE, "ARCHIVE LOG %s: lines=%d, interval=%d, graphstep=%d", param, lines, GRAPH_INTERVAL[graphstep], graphstep); |
|
454 |
|
455 while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { |
|
456 /* |
|
457 * 2014-11-15 18:39,BEER,20.312,19.750,20.0,0,NA,NA,NA,78105,NA,NA,18.000,20.1,5.312 |
|
458 * | | | | | | | | | | | | | | | |
|
459 * date_n | | | | | | | | | | | | | | |
|
460 * mode_n ----------+ | | | | | | | | | | | | | |
|
461 * air_n -----------------+ | | | | | | | | | | | | |
|
462 * beer_n -----------------------+ | | | | | | | | | | | |
|
463 * target_lo_n ------------------------+ | | | | | | | | | | |
|
464 * heater_n -------------------------------+ | | | | | | | | | |
|
465 * cooler_n ---------------------------------+ | | | | | | | | |
|
466 * not used ------------------------------------+ | | | | | | | |
|
467 * not used ---------------------------------------+ | | | | | | |
|
468 * heater_u --------------------------------------------+ | | | | | |
|
469 * cooler_u ------------------------------------------------+ | | | | |
|
470 * not used ---------------------------------------------------+ | | | |
|
471 * room_n ----------------------------------------------------------+ | | |
|
472 * target_hi_n -----------------------------------------------------------+ | |
|
473 * chiller_n ------------------------------------------------------------------+ |
|
474 */ |
|
475 hr[0] = q[0] = buffer[11]; |
|
476 hr[1] = q[1] = buffer[12]; |
|
477 q[2] = buffer[14]; |
|
478 q[3] = buffer[15]; |
|
479 hr[2] = '\0'; |
|
480 buffer[strlen(buffer) -1] = '\0'; |
|
481 date_n = strtok(buffer, ",\0"); /* timestamp */ |
|
482 mode_n = strtok(NULL, ",\0"); /* unit mode */ |
|
483 air_n = strtok(NULL, ",\0"); /* air temp */ |
|
484 beer_n = strtok(NULL, ",\0"); /* beer temp */ |
|
485 target_lo_n = strtok(NULL, ",\0"); /* target low temp */ |
|
486 heater_n = strtok(NULL, ",\0"); /* current heater state */ |
|
487 cooler_n = strtok(NULL, ",\0"); /* current cooler state */ |
|
488 heater_u = strtok(NULL, ",\0"); /* current fan state */ |
|
489 heater_u = strtok(NULL, ",\0"); /* current door state */ |
|
490 heater_u = strtok(NULL, ",\0"); /* heater use counter */ |
|
491 cooler_u = strtok(NULL, ",\0"); /* cooler use counter */ |
|
492 room_n = strtok(NULL, ",\0"); /* fan use counter */ |
|
493 room_n = strtok(NULL, ",\0"); /* room temperature */ |
|
494 target_hi_n = strtok(NULL, ",\0"); /* target high temp */ |
|
495 chiller_n = strtok(NULL, ",\0"); /* chiller temp */ |
|
496 |
|
497 if (strncmp(mode_n, (char *)"Mode", 4)) { |
|
498 /* |
|
499 * Output a line at the right intervals |
|
500 */ |
|
501 int hour = atoi(hr); |
|
502 if (((graphstep == 1)) || |
|
503 ((graphstep == 2) && (q[3] == '0' || q[3] == '5')) || |
|
504 ((graphstep == 3) && ((q[2] == '0' && q[3] == '0') || (q[2] == '1' && q[3] == '5') || (q[2] == '3' && q[3] == '0') || (q[2] == '4' && q[3] == '5'))) || |
|
505 ((graphstep == 4) && ((q[2] == '0' && q[3] == '0') || (q[2] == '3' && q[3] == '0'))) || |
|
506 ((graphstep == 5) && (q[2] == '0' && q[3] == '0')) || |
|
507 ((graphstep == 6) && (hour % 2 == 0) && (q[2] == '0' && q[3] == '0')) || /* 120 minutes */ |
|
508 ((graphstep == 7) && (hour % 4 == 0) && (q[2] == '0' && q[3] == '0')) || /* 240 minutes */ |
|
509 ((graphstep >= 8) && (hour % 8 == 0) && (q[2] == '0' && q[3] == '0')) ) { /* 480 minutes */ |
|
510 heat_used = cool_used = 0; |
|
511 if (heater_u && strcmp(heater_u, "NA") && (sscanf(heater_u, "%d", &h) == 1)) { |
|
512 if (h && heater_l) { |
|
513 heat_used = ((h - heater_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); |
|
514 } |
|
515 } |
|
516 if (cooler_u && strcmp(cooler_u, "NA") && (sscanf(cooler_u, "%d", &c) == 1)) { |
|
517 if (c && cooler_l) { |
|
518 cool_used = ((c - cooler_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); |
|
519 } |
|
520 } |
|
521 if (room_n) |
|
522 sscanf(room_n, "%f", &room_t); |
|
523 if (target_hi_n == NULL) |
|
524 target_hi_n = target_lo_n; |
|
525 snprintf(outbuf, 255, "%s,%s,%s,%s,%s,%s,%s,%d,%d,%.1f,%s,%s", |
|
526 date_n, mode_n, air_n, beer_n, target_lo_n, heater_n, cooler_n, heat_used, cool_used, room_t,target_hi_n, chiller_n); |
|
527 srv_send(outbuf); |
|
528 if (heater_u && h && strcmp(heater_u, "NA")) |
|
529 heater_l = h; |
|
530 if (cooler_u && c & strcmp(cooler_u, "NA")) |
|
531 cooler_l = c; |
|
532 } |
|
533 } |
|
534 } |
|
535 |
|
536 srv_send((char *)"."); |
|
537 fclose(fp); |
|
538 } else { |
|
539 srv_send((char *)"440 No such file"); |
|
540 } |
|
541 |
|
542 free(name); |
|
543 name = NULL; |
|
544 } |
|
545 |
|
546 return 0; |
|
547 } |
254 } |
548 |
255 |
549 |
256 |
550 |
257 |
551 int delete_Device(char *uuid) |
258 int delete_Device(char *uuid) |