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