thermferm/server.c

branch
stable
changeset 601
44d41db09466
parent 599
b44eb07cab48
child 604
e2766e538d0e
equal deleted inserted replaced
590:1ff1a95a7614 601:44d41db09466
20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *****************************************************************************/ 21 *****************************************************************************/
22 22
23 #include "rdconfig.h" 23 #include "rdconfig.h"
24 #include "thermferm.h" 24 #include "thermferm.h"
25 #include "logger.h"
26 #include "devices.h" 25 #include "devices.h"
27 #include "server.h" 26 #include "server.h"
28 #include "lcd-buffer.h" 27 #include "lcd-buffer.h"
29 #include "xutil.h" 28 #include "xutil.h"
30 #include "mqtt.h" 29 #include "mqtt.h"
204 203
205 for (tmp = lap; *tmp; tmp = &((*tmp)->next)); 204 for (tmp = lap; *tmp; tmp = &((*tmp)->next));
206 205
207 *tmp = (ls_list *)malloc(sizeof(ls_list)); 206 *tmp = (ls_list *)malloc(sizeof(ls_list));
208 (*tmp)->next = NULL; 207 (*tmp)->next = NULL;
209 strncpy((*tmp)->d_name, name, 256); 208 strncpy((*tmp)->d_name, name, 255);
210 (*tmp)->mode = mode; 209 (*tmp)->mode = mode;
211 (*tmp)->size = size; 210 (*tmp)->size = size;
212 (*tmp)->mtime = mtime; 211 (*tmp)->mtime = mtime;
213 tmp = &((*tmp)->next); 212 tmp = &((*tmp)->next);
214 } 213 }
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)
2193 for (i = 0; i < 5; i++) { 1899 for (i = 0; i < 5; i++) {
2194 if (strcmp(val, UNITMODE[i]) == 0) { 1900 if (strcmp(val, UNITMODE[i]) == 0) {
2195 unit->mqtt_flag |= MQTT_FLAG_DATA; 1901 unit->mqtt_flag |= MQTT_FLAG_DATA;
2196 /* Initialize log if the unit is turned on */ 1902 /* Initialize log if the unit is turned on */
2197 if ((unit->mode == UNITMODE_OFF) && (i != UNITMODE_OFF)) { 1903 if ((unit->mode == UNITMODE_OFF) && (i != UNITMODE_OFF)) {
2198 initlog(unit->product_code, unit->product_name);
2199 unit->mqtt_flag |= MQTT_FLAG_BIRTH; 1904 unit->mqtt_flag |= MQTT_FLAG_BIRTH;
2200 } else if ((unit->mode != UNITMODE_OFF) && (i == UNITMODE_OFF)) { 1905 } else if ((unit->mode != UNITMODE_OFF) && (i == UNITMODE_OFF)) {
2201 unit->mqtt_flag |= MQTT_FLAG_DEATH; 1906 unit->mqtt_flag |= MQTT_FLAG_DEATH;
2202 } 1907 }
2203 syslog(LOG_NOTICE, "Fermenter unit %s mode %s to %s", unit->uuid, UNITMODE[unit->mode], UNITMODE[i]); 1908 syslog(LOG_NOTICE, "Fermenter unit %s mode %s to %s", unit->uuid, UNITMODE[unit->mode], UNITMODE[i]);
2381 unit->temp_set_max = fval; 2086 unit->temp_set_max = fval;
2382 } 2087 }
2383 2088
2384 } 2089 }
2385 if (unit->mqtt_flag) { 2090 if (unit->mqtt_flag) {
2386 if (debug)
2387 fprintf(stdout, "flag value %d\n", unit->mqtt_flag);
2388 if (unit->mqtt_flag & MQTT_FLAG_BIRTH) { 2091 if (unit->mqtt_flag & MQTT_FLAG_BIRTH) {
2389 publishDBirth(unit); 2092 publishDBirth(unit);
2390 } else { 2093 } else {
2391 publishDData(unit); 2094 publishDData(unit);
2392 } 2095 }
2419 if (rlen != -1) { 2122 if (rlen != -1) {
2420 if (strlen(buf)) { 2123 if (strlen(buf)) {
2421 /* 2124 /*
2422 * Process commands from the client 2125 * Process commands from the client
2423 */ 2126 */
2424 if (strncmp(buf, "ARCHIVE", 7) == 0) { 2127 if (strncmp(buf, "DEVICE", 6) == 0) {
2425 cmd_archive(buf);
2426
2427 } else if (strncmp(buf, "DEVICE", 6) == 0) {
2428 if (cmd_device(buf)) 2128 if (cmd_device(buf))
2429 wrconfig(); 2129 wrconfig();
2430 2130
2431 } else if (strncmp(buf, "GLOBAL", 6) == 0) { 2131 } else if (strncmp(buf, "GLOBAL", 6) == 0) {
2432 if (cmd_global(buf)) 2132 if (cmd_global(buf))
2435 } else if (strncmp(buf, "HELP", 4) == 0) { 2135 } else if (strncmp(buf, "HELP", 4) == 0) {
2436 srv_send((char *)"100 Help text follows"); 2136 srv_send((char *)"100 Help text follows");
2437 srv_send((char *)"Recognized commands:"); 2137 srv_send((char *)"Recognized commands:");
2438 srv_send((char *)""); 2138 srv_send((char *)"");
2439 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 2139 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
2440 srv_send((char *)"ARCHIVE <CMD> [parameters] Archive commands");
2441 srv_send((char *)"ARCHIVE HELP Archive help screen");
2442 srv_send((char *)"DEVICE <CMD> [parameters] Device commands"); 2140 srv_send((char *)"DEVICE <CMD> [parameters] Device commands");
2443 srv_send((char *)"DEVICE HELP Device help screen"); 2141 srv_send((char *)"DEVICE HELP Device help screen");
2444 srv_send((char *)"GLOBAL <CMD> [parameters] Global commands"); 2142 srv_send((char *)"GLOBAL <CMD> [parameters] Global commands");
2445 srv_send((char *)"GLOBAL HELP Global help screen"); 2143 srv_send((char *)"GLOBAL HELP Global help screen");
2446 srv_send((char *)"LIST <CMD> [parameters] List commands"); 2144 srv_send((char *)"LIST <CMD> [parameters] List commands");

mercurial