Sat, 14 Jul 2018 17:21:25 +0200
Versie 0.6.3. MQTT device berichten alleen als een fermenter ingeschakeld is. MQTT fermenter birth en death berichhten als een fementer in of uitgeschakeld wordt. MQTT node death bericht bij normaal afsluiten van de daemon. Alle MQTT persistent berichten worden nu goed opgeruikmd.
/***************************************************************************** * Copyright (C) 2008-2018 * * Michiel Broek <mbroek at mbse dot eu> * * This file is part of the mbsePi-apps * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * mbsePi-apps is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ThermFerm; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "rdconfig.h" #include "thermferm.h" #include "logger.h" #include "devices.h" #include "server.h" #include "lcd-buffer.h" #include "xutil.h" #include "mqtt.h" extern int my_shutdown; extern int debug; extern int run_pause; extern int run_hold; extern sys_config Config; extern const char UNITMODE[5][8]; extern const char TEMPSTATE[3][8]; extern const char DEVTYPE[8][6]; extern const char DEVPRESENT[4][6]; extern const char DEVDIR[7][11]; extern const char PROFSTATE[5][6]; int s; /* connected socket */ int ls; /* listen socket */ struct sockaddr_in myaddr_in; /* for local socket address */ struct sockaddr_in peeraddr_in; /* for peer socket address */ struct hostent *hp; #define SS_BUFSIZE 1024 #define SS_TIMEOUT 300 #define MAX_INTERVALS 10 const int GRAPH_INTERVAL[MAX_INTERVALS] = { 0, 1, 5, 15, 30, 60, 120, 240, 480, 960 }; const int GRAPH_DATALINES[MAX_INTERVALS] = { 0, 800, 3200, 12000, 24000, 48000, 96000, 192000, 384000, 768000 }; const char MONTH[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; typedef struct _ls_list { struct _ls_list *next; /* Next record pointer */ char d_name[256]; /* File name */ mode_t mode; /* File mode */ off_t size; /* File size */ time_t mtime; /* File modification time */ } ls_list; void tidy_lslist(ls_list **); void fill_list(ls_list **, char *, mode_t, off_t, time_t); int comp(ls_list **,ls_list **); void sort_list(ls_list **); /* * Send message to client */ int srv_send(const char *format, ...) { char out[SS_BUFSIZE]; va_list va_ptr; if (s == -1) return -1; va_start(va_ptr, format); vsnprintf(out, SS_BUFSIZE-1, format, va_ptr); va_end(va_ptr); if (debug) { syslog(LOG_NOTICE, "send: \"%s\"", out); fprintf(stdout, "send: \"%s\"\n", out); } if (send(s, out, strlen(out), 0) != strlen(out)) { syslog(LOG_NOTICE, "srv_send failed"); return -1; } if (send(s, (char *)"\r\n", 2, 0) != 2) { syslog(LOG_NOTICE, "srv_send failed"); return -1; } return 0; } /* * Argument is a buffer of size SS_BUFSIZE. * Return -1 if error, else the number of received * character. \n is line end, ignore \r. */ int srv_recv(char *buffer) { int bytesloaded = 0; ssize_t ret; unsigned char buf; socklen_t fromlen; memset(buffer, 0, SS_BUFSIZE); while(1) { /* * read a single byte */ fromlen = sizeof(peeraddr_in); ret = recvfrom(s, &buf, 1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); if (ret < 0) { syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); return -1; /* error */ } else if (ret == 0) { return -1; /* no data */ } if (buf == '\n') break; if (buf != '\r') { buffer[bytesloaded] = buf; bytesloaded++; } } if (debug) { syslog(LOG_NOTICE, "recv: %d `%s'", bytesloaded, buffer); fprintf(stdout, "recv: %d `%s'\n", bytesloaded, buffer); } return bytesloaded; } /* * Update the device inuse counter. */ void device_count(int plus, char *uuid) { devices_list *device; for (device = Config.devices; device; device = device->next) { if (strcmp(device->uuid, uuid) == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (plus == TRUE) { device->inuse++; } else { if (device->inuse) device->inuse--; } #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } } int delete_Profile(char *uuid) { profiles_list *current = Config.profiles; profiles_list *previous = NULL; prof_step *step, *olds; while (current) { if (strcmp(current->uuid, uuid) == 0) { if (previous == NULL) { Config.profiles = current->next; free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; if (current->steps) { for (step = current->steps; step; step = olds) { olds = step->next; free(step); } current->steps = NULL; } free(current); return 1; } else { free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; if (current->steps) { for (step = current->steps; step; step = olds) { olds = step->next; free(step); } current->steps = NULL; } previous->next = current->next; free(current); current = previous->next; return 1; } } else { previous = current; current = current->next; } } return 0; } void tidy_lslist(ls_list **lap) { ls_list *tmp, *old; for (tmp = *lap; tmp; tmp = old) { old = tmp->next; free(tmp); } *lap = NULL; } void fill_list(ls_list **lap, char *name, mode_t mode, off_t size, time_t mtime) { ls_list **tmp; for (tmp = lap; *tmp; tmp = &((*tmp)->next)); *tmp = (ls_list *)malloc(sizeof(ls_list)); (*tmp)->next = NULL; strncpy((*tmp)->d_name, name, 256); (*tmp)->mode = mode; (*tmp)->size = size; (*tmp)->mtime = mtime; tmp = &((*tmp)->next); } void sort_list(ls_list **lap) { ls_list *ta, **vector; size_t n = 0, i; if (*lap == NULL) return; for (ta = *lap; ta; ta = ta->next) n++; vector = (ls_list **)malloc(n * sizeof(ls_list *)); i = 0; for (ta = *lap; ta; ta = ta->next) { vector[i++] = ta; } qsort(vector, n, sizeof(ls_list *), (int(*)(const void*, const void*))comp); (*lap) = vector[0]; i = 1; for (ta = *lap; ta; ta = ta->next) { if (i < n) ta->next = vector[i++]; else ta->next = NULL; } free(vector); return; } int comp(ls_list **lsp1, ls_list **lsp2) { return strcmp((*lsp1)->d_name, (*lsp2)->d_name); } /* * ARCHIVE DIR * ARCHIVE GET filename * ARCHIVE LOG filename * ARCHIVE HELP */ int cmd_archive(char *buf) { char *opt, *param, *name = NULL, *filename = NULL, *logname = NULL, mbits[11], tstr[24]; DIR *dd; FILE *fp; struct dirent entry, *result; ls_list *lsx = NULL, *tmp; struct stat sbuf; struct tm *tbuf; time_t ftime; int found; units_list *unit; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } param = strtok(NULL, "\0"); if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"ARCHIVE DIR Archived logfiles directory"); srv_send((char *)"ARCHIVE GET filename Archived logfile download"); srv_send((char *)"ARCHIVE LOG filename Archived logfile data in graphsteps"); srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"DIR") == 0) { if (getenv((char *)"USER") == NULL) { name = xstrcpy((char *)"/root"); } else { name = xstrcpy(getenv((char *)"HOME")); } name = xstrcat(name, (char *)"/.thermferm/log/"); if ((dd = opendir(name))) { for (;;) { if ((readdir_r(dd, &entry, &result)) != 0) { syslog(LOG_NOTICE, "readdir_r: error=%d", errno); break; } if (result == NULL) /* End of directory */ break; if (result->d_name[0] != '.') { filename = xstrcpy(name); filename = xstrcat(filename, result->d_name); /* * Remove files from the list when they are in use */ found = 0; for (unit = Config.units; unit; unit = unit->next) { if (unit->mode != UNITMODE_OFF) { logname = xstrcpy(unit->name); logname = xstrcat(logname, (char *)".log"); if (! strcmp(result->d_name, logname)) found = 1; free(logname); logname = NULL; } } if ((found == 0) && ((stat(filename, &sbuf)) == 0)) { fill_list(&lsx, result->d_name, sbuf.st_mode, sbuf.st_size, sbuf.st_mtime); } free(filename); filename = NULL; } } closedir(dd); } else { syslog(LOG_NOTICE, "opendir: \"%s\" error=%d", name, errno); } sort_list(&lsx); srv_send((char *)"212 Archive directory follows:"); for (tmp = lsx; tmp; tmp = tmp->next) { sprintf(mbits, "----------"); if (tmp->mode & S_IRUSR) mbits[1] = 'r'; if (tmp->mode & S_IWUSR) mbits[2] = 'w'; if (tmp->mode & S_IXUSR) mbits[3] = 'x'; if (tmp->mode & S_IRGRP) mbits[4] = 'r'; if (tmp->mode & S_IWGRP) mbits[5] = 'w'; if (tmp->mode & S_IXGRP) mbits[6] = 'x'; if (tmp->mode & S_IROTH) mbits[7] = 'r'; if (tmp->mode & S_IWOTH) mbits[8] = 'w'; if (tmp->mode & S_IXOTH) mbits[9] = 'x'; ftime = tmp->mtime; tbuf = localtime(&ftime); sprintf(tstr, "%02d %s %04d %02d:%02d", tbuf->tm_mday, MONTH[tbuf->tm_mon], tbuf->tm_year+1900, tbuf->tm_hour, tbuf->tm_min); srv_send((char *)"%s,%s,%d,%s", tmp->d_name, mbits, tmp->size, tstr); } srv_send((char *)"."); tidy_lslist(&lsx); free(name); name = NULL; return 0; } if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 0; } if (strcmp(opt, (char *)"GET") == 0) { if (getenv((char *)"USER") == NULL) { name = xstrcpy((char *)"/root"); } else { name = xstrcpy(getenv((char *)"HOME")); } name = xstrcat(name, (char *)"/.thermferm/log/"); name = xstrcat(name, param); if ((fp = fopen(name, "r"))) { char buffer[256]; srv_send((char *)"212 Archive file follows:"); while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { int i; for (i = 0; i < strlen(buffer); i++) { if (buffer[i] == '\n') buffer[i] = '\0'; if (buffer[i] == '\r') buffer[i] = '\0'; } srv_send(buffer); } srv_send((char *)"."); fclose(fp); } else { srv_send((char *)"440 No such file"); } free(name); name = NULL; return 0; } if (strcmp(opt, (char *)"LOG") == 0) { if (getenv((char *)"USER") == NULL) { name = xstrcpy((char *)"/root"); } else { name = xstrcpy(getenv((char *)"HOME")); } name = xstrcat(name, (char *)"/.thermferm/log/"); name = xstrcat(name, param); if ((fp = fopen(name, "r"))) { char buffer[256], outbuf[256], q[5], hr[3]; char *date_n, *mode_n, *air_n, *beer_n, *target_lo_n, *target_hi_n, *heater_n, *cooler_n, *room_n; char *heater_u, *cooler_u; int lines = 0, heater_l = 0, cooler_l = 0, h = 0, c = 0, heat_used = 0, cool_used = 0, graphstep = 0; float room_t = 0.0; srv_send((char *)"212 Logfile list follows:"); while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { lines++; } fseek(fp, 0L, SEEK_SET); /* * We have counted the lines in the logfile including the header lines. * The header lines should be ignored but there are so few of them, we * just include them in the total. * Now find a reasonable interval of lines to sent to the client. */ for (graphstep = 1; graphstep <= MAX_INTERVALS; graphstep++) { if (lines < GRAPH_DATALINES[graphstep]) { break; } } if (graphstep > MAX_INTERVALS) graphstep = MAX_INTERVALS; syslog(LOG_NOTICE, "ARCHIVE LOG %s: lines=%d, interval=%d, graphstep=%d", param, lines, GRAPH_INTERVAL[graphstep], graphstep); while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { /* * 2014-11-15 18:39,BEER,20.312,19.750,20.0,0,NA,NA,NA,78105,NA,NA,18.000,20.1 * | | | | | | | | | | | | | | * date_n | | | | | | | | | | | | | * mode_n ----------+ | | | | | | | | | | | | * air_n -----------------+ | | | | | | | | | | | * beer_n -----------------------+ | | | | | | | | | | * target_lo_n ------------------------+ | | | | | | | | | * heater_n -------------------------------+ | | | | | | | | * cooler_n ---------------------------------+ | | | | | | | * not used ------------------------------------+ | | | | | | * not used ---------------------------------------+ | | | | | * heater_u --------------------------------------------+ | | | | * cooler_u ------------------------------------------------+ | | | * not used ---------------------------------------------------+ | | * room_n ----------------------------------------------------------+ | * target_hi_n -----------------------------------------------------------+ */ hr[0] = q[0] = buffer[11]; hr[1] = q[1] = buffer[12]; q[2] = buffer[14]; q[3] = buffer[15]; hr[2] = '\0'; buffer[strlen(buffer) -1] = '\0'; date_n = strtok(buffer, ",\0"); /* timestamp */ mode_n = strtok(NULL, ",\0"); /* unit mode */ air_n = strtok(NULL, ",\0"); /* air temp */ beer_n = strtok(NULL, ",\0"); /* beer temp */ target_lo_n = strtok(NULL, ",\0"); /* target low temp */ heater_n = strtok(NULL, ",\0"); /* current heater state */ cooler_n = strtok(NULL, ",\0"); /* current cooler state */ heater_u = strtok(NULL, ",\0"); /* current fan state */ heater_u = strtok(NULL, ",\0"); /* current door state */ heater_u = strtok(NULL, ",\0"); /* heater use counter */ cooler_u = strtok(NULL, ",\0"); /* cooler use counter */ room_n = strtok(NULL, ",\0"); /* fan use counter */ room_n = strtok(NULL, ",\0"); /* room temperature */ target_hi_n = strtok(NULL, ",\0"); /* target high temp */ if (strncmp(mode_n, (char *)"Mode", 4)) { /* * Output a line at the right intervals */ int hour = atoi(hr); if (((graphstep == 1)) || ((graphstep == 2) && (q[3] == '0' || q[3] == '5')) || ((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'))) || ((graphstep == 4) && ((q[2] == '0' && q[3] == '0') || (q[2] == '3' && q[3] == '0'))) || ((graphstep == 5) && (q[2] == '0' && q[3] == '0')) || ((graphstep == 6) && (hour % 2 == 0) && (q[2] == '0' && q[3] == '0')) || /* 120 minutes */ ((graphstep == 7) && (hour % 4 == 0) && (q[2] == '0' && q[3] == '0')) || /* 240 minutes */ ((graphstep >= 8) && (hour % 8 == 0) && (q[2] == '0' && q[3] == '0')) ) { /* 480 minutes */ heat_used = cool_used = 0; if (heater_u && strcmp(heater_u, "NA") && (sscanf(heater_u, "%d", &h) == 1)) { if (h && heater_l) { heat_used = ((h - heater_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); } } if (cooler_u && strcmp(cooler_u, "NA") && (sscanf(cooler_u, "%d", &c) == 1)) { if (c && cooler_l) { cool_used = ((c - cooler_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); } } if (room_n) sscanf(room_n, "%f", &room_t); if (target_hi_n == NULL) target_hi_n = target_lo_n; snprintf(outbuf, 255, "%s,%s,%s,%s,%s,%s,%s,%d,%d,%.1f,%s", date_n, mode_n, air_n, beer_n, target_lo_n, heater_n, cooler_n, heat_used, cool_used, room_t,target_hi_n); srv_send(outbuf); if (heater_u && h && strcmp(heater_u, "NA")) heater_l = h; if (cooler_u && c & strcmp(cooler_u, "NA")) cooler_l = c; } } } srv_send((char *)"."); fclose(fp); } else { srv_send((char *)"440 No such file"); } free(name); name = NULL; } return 0; } int delete_Device(char *uuid) { devices_list *current = Config.devices; devices_list *previous = NULL; while (current) { if (strcmp(current->uuid, uuid) == 0) { if (previous == NULL) { Config.devices = current->next; free(current->uuid); current->uuid = NULL; free(current->address); current->address = NULL; free(current->description); current->description = NULL; free(current->comment); current->comment = NULL; free(current); return 1; } else { free(current->uuid); current->uuid = NULL; free(current->address); current->address = NULL; free(current->description); current->description = NULL; free(current->comment); current->comment = NULL; previous->next = current->next; free(current); current = previous->next; return 1; } } else { previous = current; current = current->next; } } return 0; } /* * DEVICE ADD type * DEVICE DEL uuid * DEVICE LIST * DEVICE GET uuid * DEVICE PUT uuid */ int cmd_device(char *buf) { char *opt, *param, *kwd, *val, ibuf[SS_BUFSIZE]; devices_list *device, *tmpd; int i, rc, rlen, ival; uuid_t uu; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } param = strtok(NULL, "\0"); if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"DEVICE ADD type Add device (RC433/DHT/I2C/SPI)"); srv_send((char *)"DEVICE DEL uuid Delete device by uuid"); srv_send((char *)"DEVICE LIST List all devices"); srv_send((char *)"DEVICE GET uuid Read device by uuid parameters"); srv_send((char *)"DEVICE PUT uuid Write device by uuid parameters"); srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"LIST") == 0) { srv_send((char *)"212 Devices list follows:"); for (device = Config.devices; device; device = device->next) { srv_send((char *)"%s,%s,%d,%d,%s,%s,%d", device->uuid, device->address, device->subdevice, device->inuse, device->comment, DEVDIR[device->direction], device->value + device->offset); } srv_send((char *)"."); return 0; } if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 1; } if (strcmp(opt, (char *)"ADD") == 0) { if ((strcmp(param, (char *)"RC433") == 0) || (strcmp(param, (char *)"DHT") == 0) || (strcmp(param, (char *)"I2C") == 0) || (strcmp(param, (char *)"SPI") == 0)) { device = (devices_list *)malloc(sizeof(devices_list)); device->next = NULL; device->version = 1; device->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, device->uuid); for (i = 0; i < 8; i++) { if (strcmp(param, DEVTYPE[i]) == 0) { device->type = i; break; } } device->direction = DEVDIR_UNDEF; device->value = device->offset = device->subdevice = device->inuse = 0; device->present = DEVPRESENT_UNDEF; device->address = xstrcpy((char *)"Enter address here"); device->gpiopin = -1; device->description = xstrcpy((char *)"Describe me here"); device->comment = xstrcpy((char *)"Comment here"); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (Config.devices == NULL) { Config.devices = device; } else { for (tmpd = Config.devices; tmpd; tmpd = tmpd->next) { if (tmpd->next == NULL) { tmpd->next = device; break; } } } #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif syslog(LOG_NOTICE, "Device %s added", device->uuid); srv_send((char *)"211 Device %s added", device->uuid); return 1; } else { srv_send((char *)"503 Parameter error"); return 0; } } if (strcmp(opt, (char *)"DEL") == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif rc = delete_Device(param); #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif if (rc) { syslog(LOG_NOTICE, "Device %s deleted", param); srv_send((char *)"211 Device %s deleted", param); return 1; } else { srv_send((char *)"440 No such device"); return 0; } } if (strcmp(opt, (char *)"GET") == 0) { for (device = Config.devices; device; device = device->next) { if (strcmp(device->uuid, param) == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif int my_value = device->value; int my_timestamp = (int)device->timestamp; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif srv_send((char *)"213 Device record follows:"); srv_send((char *)"TYPE,%s", DEVTYPE[device->type]); srv_send((char *)"ADDRESS,%s", device->address); srv_send((char *)"DIRECTION,%s", DEVDIR[device->direction]); srv_send((char *)"VALUE,%d", my_value); srv_send((char *)"OFFSET,%d", device->offset); srv_send((char *)"PRESENT,%s", DEVPRESENT[device->present]); srv_send((char *)"SUBDEVICE,%d", device->subdevice); srv_send((char *)"GPIOPIN,%d", device->gpiopin); srv_send((char *)"DESCRIPTION,%s", device->description); srv_send((char *)"INUSE,%d", device->inuse); srv_send((char *)"COMMENT,%s", device->comment); srv_send((char *)"TIMESTAMP,%d", my_timestamp); srv_send((char *)"."); return 0; } } srv_send((char *)"440 No such device"); return 0; } if (strcmp(opt, (char *)"PUT") == 0) { for (device = Config.devices; device; device = device->next) { if (strcmp(device->uuid, param) == 0) { while (1) { rlen = srv_recv(ibuf); if (rlen == -1) { return 0; } if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Device record"); return 1; } kwd = strtok(ibuf, ",\0"); val = strtok(NULL, "\0"); if (kwd && val) { if (strcmp(kwd, (char *)"TYPE") == 0) { for (i = 0; i < 8; i++) { if (strcmp(val, DEVTYPE[i]) == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->type != i) syslog(LOG_NOTICE, "Device %s changed type %s to %s", device->uuid, DEVTYPE[device->type], DEVTYPE[i]); device->type = i; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif break; } } } else if (strcmp(kwd, (char *)"DIRECTION") == 0) { for (i = 0; i < 7; i++) { if (strcmp(val, DEVDIR[i]) == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->direction != i) syslog(LOG_NOTICE, "Device %s changed direction %s to %s", device->uuid, DEVDIR[device->type], DEVDIR[i]); device->direction = i; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif break; } } } else if (strcmp(kwd, (char *)"VALUE") == 0) { if (sscanf(val, "%d", &ival) == 1) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->value != ival) syslog(LOG_NOTICE, "Device %s changed value %d to %d", device->uuid, device->value, ival); device->value = ival; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } else if (strcmp(kwd, (char *)"OFFSET") == 0) { if (sscanf(val, "%d", &ival) == 1) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->offset != ival) syslog(LOG_NOTICE, "Device %s changed offset %d to %d", device->uuid, device->offset, ival); device->offset = ival; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } else if (strcmp(kwd, (char *)"PRESENT") == 0) { for (i = 0; i < 4; i++) { if (strcmp(val, DEVPRESENT[i]) == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->present != i) syslog(LOG_NOTICE, "Device %s changed present %s to %s", device->uuid, DEVPRESENT[device->present], DEVPRESENT[i]); device->present = i; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif break; } } } else if (strcmp(kwd, (char *)"ADDRESS") == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->address) { if (strcmp(device->address, val)) syslog(LOG_NOTICE, "Device %s changed address `%s' to `%s'", device->uuid, device->address, val); free(device->address); } device->address = xstrcpy(val); #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } else if (strcmp(kwd, (char *)"SUBDEVICE") == 0) { if (sscanf(val, "%d", &ival) == 1) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->subdevice != ival) syslog(LOG_NOTICE, "Device %s changed subdevice %d to %d", device->uuid, device->subdevice, ival); device->subdevice = ival; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } else if (strcmp(kwd, (char *)"GPIOPIN") == 0) { if (sscanf(val, "%d", &ival) == 1) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->gpiopin != ival) syslog(LOG_NOTICE, "Device %s changed gpiopin %d to %d", device->uuid, device->gpiopin, ival); device->gpiopin = ival; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } else if (strcmp(kwd, (char *)"DESCRIPTION") == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->description) { if (strcmp(device->description, val)) syslog(LOG_NOTICE, "Device %s changed description `%s' to `%s'", device->uuid, device->description, val); free(device->description); } device->description = xstrcpy(val); #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } else if (strcmp(kwd, (char *)"COMMENT") == 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (device->comment) { if (strcmp(device->comment, val)) syslog(LOG_NOTICE, "Device %s changed comment `%s' to `%s'", device->uuid, device->comment, val); free(device->comment); } device->comment = xstrcpy(val); #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } } } } } srv_send((char *)"440 No such device"); return 0; } srv_send((char *)"504 Subcommand error"); return 0; } /* * GLOBAL GET * GLOBAL PUT */ int cmd_global(char *buf) { char *opt, *kwd, *val, ibuf[SS_BUFSIZE]; int ival, rlen; opt = strtok(buf, " \0"); opt = strtok(NULL, "\0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"GLOBAL GET Get global settings"); srv_send((char *)"GLOBAL PUT Put global settings"); srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"GET") == 0) { srv_send((char *)"213 Global Settings record follows:"); srv_send((char *)"RELEASE,%s", VERSION); srv_send((char *)"NAME,%s", Config.name); srv_send((char *)"PORT,%d", Config.my_port); srv_send((char *)"TEMPFORMAT,%c", Config.tempFormat); srv_send((char *)"TEMP_ADDRESS,%s", Config.temp_address); srv_send((char *)"TEMP_STATE,%s", TEMPSTATE[Config.temp_state]); srv_send((char *)"TEMP_VALUE,%.1f", Config.temp_value / 1000.0); srv_send((char *)"HUM_ADDRESS,%s", Config.hum_address); srv_send((char *)"HUM_STATE,%s", TEMPSTATE[Config.hum_state]); srv_send((char *)"HUM_VALUE,%.0f", Config.hum_value / 1000.0); srv_send((char *)"TEMP_HUM_IDX,%d", Config.temp_hum_idx); srv_send((char *)"LCD_COLS,%d", Config.lcd_cols); srv_send((char *)"LCD_ROWS,%d", Config.lcd_rows); srv_send((char *)"NEXT_UNIT,%d", Config.next_unit); #ifdef HAVE_MOSQUITTO_H srv_send((char *)"MQTT_HOST,%s", Config.mqtt_host); srv_send((char *)"MQTT_PORT,%d", Config.mqtt_port); #endif srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"PUT") == 0) { while (1) { rlen = srv_recv(ibuf); if (rlen == -1) { return 0; } if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Global record"); return 1; } kwd = strtok(ibuf, ",\0"); val = strtok(NULL, "\0"); if (kwd) { if (strcmp(kwd, (char *)"NAME") == 0) { if (val && Config.name && strcmp(val, Config.name)) syslog(LOG_NOTICE, "Global name `%s' to `%s'", Config.name, val); if (Config.name) free(Config.name); if (val) Config.name = xstrcpy(val); else Config.name = NULL; } else if (val && (strcmp(kwd, (char *)"PORT") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (Config.my_port != ival) syslog(LOG_NOTICE, "Global port %d to %d", Config.my_port, ival); Config.my_port = ival; } } else if (val && (strcmp(kwd, (char *)"TEMPFORMAT") == 0)) { if ((val[0] == 'C') || (val[0] == 'F')) { if (Config.tempFormat != val[0]) syslog(LOG_NOTICE, "Global port %c to %c", Config.tempFormat, val[0]); Config.tempFormat = val[0]; } } else if (strcmp(kwd, (char *)"TEMP_ADDRESS") == 0) { if (val && Config.temp_address && (strcmp(val, Config.temp_address))) syslog(LOG_NOTICE, "Global temperature address `%s' to `%s'", Config.temp_address, val); if (Config.temp_address) { device_count(FALSE, Config.temp_address); free(Config.temp_address); } if (val) { Config.temp_address = xstrcpy(val); device_count(TRUE, Config.temp_address); } else Config.temp_address = NULL; } else if (strcmp(kwd, (char *)"HUM_ADDRESS") == 0) { if (val && Config.hum_address && (strcmp(val, Config.hum_address))) syslog(LOG_NOTICE, "Global humidity address `%s' to `%s'", Config.hum_address, val); if (Config.hum_address) { device_count(FALSE, Config.hum_address); free(Config.hum_address); } if (val) { Config.hum_address = xstrcpy(val); device_count(TRUE, Config.hum_address); } else Config.hum_address = NULL; } else if (val && (strcmp(kwd, (char *)"TEMP_HUM_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (Config.temp_hum_idx != ival) syslog(LOG_NOTICE, "Global Temp/Humidity idx %d to %d", Config.temp_hum_idx, ival); Config.temp_hum_idx = ival; } } else if (val && (strcmp(kwd, (char *)"LCD_COLS") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (Config.lcd_cols != ival) syslog(LOG_NOTICE, "Global LCD columns %d to %d", Config.lcd_cols, ival); Config.lcd_cols = ival; } } else if (val && (strcmp(kwd, (char *)"LCD_ROWS") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (Config.lcd_rows != ival) syslog(LOG_NOTICE, "Global LCD rows %d to %d", Config.lcd_rows, ival); Config.lcd_rows = ival; } } } } } } srv_send((char *)"504 Subcommand error"); return 0; } /* * LIST * LIST LOG */ int cmd_list(char *buf) { char *opt, *param, *filename, q[5], hr[3], buffer[256], outbuf[256]; char *date_n, *mode_n, *air_n, *beer_n, *target_lo_n, *target_hi_n, *heater_n, *cooler_n, *room_n; char *heater_u, *cooler_u; int heater_l = 0, cooler_l = 0, h = 0, c = 0, heat_used = 0, cool_used = 0, lines = 0, graphstep = 0; units_list *unit; FILE *fp; float room_t; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { /* * Default, list available units */ srv_send((char *)"212 Fermenter list follows:"); for (unit = Config.units; unit; unit = unit->next) { srv_send((char *)"%s,%s,%s", unit->uuid, unit->name, UNITMODE[unit->mode]); } srv_send((char *)"."); return 0; } else if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"LIST List available units"); srv_send((char *)"LIST LOG uuid List logfile of unit by uuid"); srv_send((char *)"."); return 0; } else if (strcmp(opt, (char *)"LOG") == 0) { param = strtok(NULL, "\0"); if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 0; } q[0] = q[1] = q[2] = q[3] = q[4] = 'a'; for (unit = Config.units; unit; unit = unit->next) { if (strcmp(param, unit->uuid) == 0) break; } srv_send((char *)"212 Logfile list follows:"); if (getenv((char *)"USER") == NULL) { filename = xstrcpy((char *)"/root"); } else { filename = xstrcpy(getenv((char *)"HOME")); } filename = xstrcat(filename, (char *)"/.thermferm/log/"); filename = xstrcat(filename, unit->name); filename = xstrcat(filename, (char *)".log"); if ((fp = fopen(filename, "r"))) { /* * Count the lines in the logfile */ lines = 0; while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { lines++; } fseek(fp, 0L, SEEK_SET); /* * We have counted the lines in the logfile including the header lines. * The header lines should be ignored but there are so few of them, we * just include them in the total. * Now find a reasonable interval of lines to sent to the client. */ for (graphstep = 1; graphstep <= MAX_INTERVALS; graphstep++) { if (lines < GRAPH_DATALINES[graphstep]) { break; } } if (graphstep > MAX_INTERVALS) graphstep = MAX_INTERVALS; syslog(LOG_NOTICE, "LIST LOG %s: lines=%d, interval=%d, graphstep=%d", unit->name, lines, GRAPH_INTERVAL[graphstep], graphstep); while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) { /* * 2014-11-15 18:39,BEER,20.312,19.750,20.0,0,NA,NA,NA,78105,NA,NA */ hr[0] = q[0] = buffer[11]; hr[1] = q[1] = buffer[12]; q[2] = buffer[14]; q[3] = buffer[15]; hr[2] = '\0'; buffer[strlen(buffer) -1] = '\0'; date_n = strtok(buffer, ",\0"); /* timestamp */ mode_n = strtok(NULL, ",\0"); /* unit mode */ air_n = strtok(NULL, ",\0"); /* air temp */ beer_n = strtok(NULL, ",\0"); /* beer temp */ target_lo_n = strtok(NULL, ",\0"); /* target low temp */ heater_n = strtok(NULL, ",\0"); /* current heater state */ cooler_n = strtok(NULL, ",\0"); /* current cooler state */ heater_u = strtok(NULL, ",\0"); /* current fan state */ heater_u = strtok(NULL, ",\0"); /* current door state */ heater_u = strtok(NULL, ",\0"); /* heater use counter */ cooler_u = strtok(NULL, ",\0"); /* cooler use counter */ room_n = strtok(NULL, ",\0"); /* fan use counter */ room_n = strtok(NULL, ",\0"); /* room temperature */ target_hi_n = strtok(NULL, ",\0"); /* target high temp */ if (strncmp(mode_n, (char *)"Mode", 4)) { /* * Output a line at the right intervals */ int hour = atoi(hr); if (((graphstep == 1)) || ((graphstep == 2) && (q[3] == '0' || q[3] == '5')) || ((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'))) || ((graphstep == 4) && ((q[2] == '0' && q[3] == '0') || (q[2] == '3' && q[3] == '0'))) || ((graphstep == 5) && (q[2] == '0' && q[3] == '0')) || ((graphstep == 6) && (hour % 2 == 0) && (q[2] == '0' && q[3] == '0')) || /* 120 minutes */ ((graphstep == 7) && (hour % 4 == 0) && (q[2] == '0' && q[3] == '0')) || /* 240 minutes */ ((graphstep >= 8) && (hour % 8 == 0) && (q[2] == '0' && q[3] == '0')) ) { /* 480 minutes */ heat_used = cool_used = 0; if (strcmp(heater_u, "NA") && (sscanf(heater_u, "%d", &h) == 1)) { if (h && heater_l) { heat_used = ((h - heater_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); } } if (strcmp(cooler_u, "NA") && (sscanf(cooler_u, "%d", &c) == 1)) { if (c && cooler_l) { cool_used = ((c - cooler_l) * 100) / (GRAPH_INTERVAL[graphstep] * 60); } } if (room_n) sscanf(room_n, "%f", &room_t); else room_t = 0.0; if (target_hi_n == NULL) target_hi_n = target_lo_n; snprintf(outbuf, 255, "%s,%s,%s,%s,%s,%s,%s,%d,%d,%.1f,%s", date_n, mode_n, air_n, beer_n, target_lo_n, heater_n, cooler_n, heat_used, cool_used, room_t, target_hi_n); srv_send(outbuf); if (h && strcmp(heater_u, "NA")) heater_l = h; if (c & strcmp(cooler_u, "NA")) cooler_l = c; } } } } free(filename); filename = NULL; srv_send((char *)"."); return 0; } srv_send((char *)"504 Subcommand error"); return 0; } /* * PROFILE ADD name Add a new profile * PROFILE DEL uuid Delete profile with uuid * PROFILE LIST List available profiles * PROFILE GET uuid Get profile record * PROFILE PUT uuid Put profile record * PROFILE GETS uuid Get profile steps list * PROFILE PUTS uuid Put profile steps list */ int cmd_profile(char *buf) { char ibuf[SS_BUFSIZE], *sstep, *rest, *tlarg, *tharg, *frarg, *param, *kwd, *val; int j, ival, rlen, istep, irest, ifrarg; float ftlarg, ftharg, fval; char *opt; profiles_list *profile, *tmpp; prof_step *step, *olds; uuid_t uu; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"PROFILE uuid,name Profile rename"); srv_send((char *)"PROFILE ADD name Add new Profile with name"); srv_send((char *)"PROFILE DEL uuid Delete Profile by uuid"); srv_send((char *)"PROFILE LIST List available profiles"); srv_send((char *)"PROFILE GET uuid Get Profile record by uuid"); srv_send((char *)"PROFILE PUT uuid Put Profile record by uuid"); srv_send((char *)"PROFILE GETS uuid Profile get steps list"); srv_send((char *)"PROFILE PUTS uuid Profile put steps list"); srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"LIST") == 0) { /* * Fermenting profiles */ srv_send((char *)"212 Profiles list follows:"); for (profile = Config.profiles; profile; profile = profile->next) { j = 0; for (step = profile->steps; step; step = step->next) j++; srv_send((char *)"%s,%s,%d,%d", profile->uuid, profile->name, j, profile->busy); } srv_send((char *)"."); return 0; } param = strtok(NULL, "\0"); if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 0; } if (strcmp(opt, (char *)"ADD") == 0) { profile = (profiles_list *)malloc(sizeof(profiles_list)); profile->next = NULL; profile->version = 1; profile->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, profile->uuid); profile->name = xstrcpy(param); profile->busy = profile->fridge_mode = 0; profile->inittemp_lo = 19.8; profile->inittemp_hi = 20.2; profile->steps = NULL; if (Config.profiles == NULL) { Config.profiles = profile; } else { for (tmpp = Config.profiles; tmpp; tmpp = tmpp->next) { if (tmpp->next == NULL) { tmpp->next = profile; break; } } } syslog(LOG_NOTICE, "Profile %s added", profile->uuid); srv_send((char *)"211 Profile %s added", profile->uuid); return 1; } else if (strcmp(opt, (char *)"DEL") == 0) { if (delete_Profile(param)) { syslog(LOG_NOTICE, "Profile %s deleted", param); srv_send((char *)"211 Profile %s deleted", param); return 1; } else { srv_send((char *)"440 No such profile"); return 0; } } else if (strcmp(opt, (char *)"GET") == 0) { for (profile = Config.profiles; profile; profile = profile->next) { if (strcmp(profile->uuid, param) == 0) { srv_send((char *)"213 Profile record follows:"); srv_send((char *)"UUID,%s", profile->uuid); srv_send((char *)"NAME,%s", profile->name); srv_send((char *)"INITTEMP_LO,%.1f", profile->inittemp_lo); srv_send((char *)"INITTEMP_HI,%.1f", profile->inittemp_hi); srv_send((char *)"FRIDGE_MODE,%d", profile->fridge_mode); srv_send((char *)"."); return 0; } } srv_send((char *)"440 No such profile"); return 0; } else if (strcmp(opt, (char *)"PUT") == 0) { for (profile = Config.profiles; profile; profile = profile->next) { if (strcmp(profile->uuid, param) == 0) { while (1) { rlen = srv_recv(ibuf); if (rlen == -1) { return 0; } if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Profile record"); return 1; } kwd = strtok(ibuf, ",\0"); val = strtok(NULL, "\0"); if (kwd && val) { if (strcmp(kwd, (char *)"NAME") == 0) { if (profile->name) { if (strcmp(profile->name, val)) syslog(LOG_NOTICE, "Profile %s name `%s' to `%s'", profile->uuid, profile->name, val); free(profile->name); } profile->name = xstrcpy(val); } else if (strcmp(kwd, (char *)"INITTEMP_LO") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (profile->inittemp_lo != fval) syslog(LOG_NOTICE, "Profile %s initial temperature low %.1f to %.1f", profile->uuid, profile->inittemp_lo, fval); profile->inittemp_lo = fval; } } else if (strcmp(kwd, (char *)"INITTEMP_HI") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (profile->inittemp_hi != fval) syslog(LOG_NOTICE, "Profile %s initial temperature high %.1f to %.1f", profile->uuid, profile->inittemp_hi, fval); profile->inittemp_hi = fval; } } else if (strcmp(kwd, (char *)"FRIDGE_MODE") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (profile->fridge_mode != ival) syslog(LOG_NOTICE, "Profile %s fridge mode %d to %d", profile->uuid, profile->fridge_mode, ival); profile->fridge_mode = ival; } } } } } } } srv_send((char *)"440 No such profile"); return 0; } else if (strcmp(opt, (char *)"GETS") == 0) { for (profile = Config.profiles; profile; profile = profile->next) { if (strcmp(profile->uuid, param) == 0) { srv_send((char *)"215 Profile steps follow:"); for (step = profile->steps; step; step = step->next) { srv_send((char *)"%d,%d,%.1f,%.1f,%d", step->steptime, step->resttime, step->target_lo, step->target_hi, step->fridge_mode); } srv_send((char *)"."); return 0; } } srv_send((char *)"440 No such profile"); return 0; } else if (strcmp(opt, (char *)"PUTS") == 0) { for (profile = Config.profiles; profile; profile = profile->next) { if (strcmp(profile->uuid, param) == 0) { if (profile->steps) { syslog(LOG_NOTICE, "PROFILE PUTS %s erased all old steps", profile->uuid); for (step = profile->steps; step; step = olds) { olds = step->next; free(step); } profile->steps = NULL; } j = 0; while (1) { rlen = srv_recv(ibuf); if (rlen == -1) { return 0; } else { if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Profile steps"); return 1; } sstep = strtok(ibuf, ",\0"); rest = strtok(NULL, ",\0"); tlarg = strtok(NULL, ",\0"); tharg = strtok(NULL, ",\0"); frarg = strtok(NULL, "\0"); if ((sscanf(sstep, "%d", &istep) == 1) && (sscanf(rest, "%d", &irest) == 1) && (sscanf(tlarg, "%f", &ftlarg) == 1) && (sscanf(tharg, "%f", &ftharg) == 1) && (sscanf(frarg, "%d", &ifrarg) == 1)) { j++; syslog(LOG_NOTICE, "PROFILE PUTS %s add step %d: steptime=%d resttime=%d target=%.1f..%.1f fridge_mode=%d", profile->uuid, j, istep, irest, ftlarg, ftharg, ifrarg); step = (prof_step *)malloc(sizeof(prof_step)); step->next = NULL; step->version = 1; step->steptime = istep; step->resttime = irest; step->target_lo = ftlarg; step->target_hi = ftharg; step->fridge_mode = ifrarg; if (profile->steps == NULL) { profile->steps = step; } else { for (olds = profile->steps; olds; olds = olds->next) { if (olds->next == NULL) { olds->next = step; break; } } } } } } } } } srv_send((char *)"440 No such profile"); return 0; } srv_send((char *)"504 Subcommand error"); return 0; } #ifdef USE_SIMULATOR int delete_Simulator(char *uuid) { simulator_list *current = Config.simulators; simulator_list *previous = NULL; while (current) { if (strcmp(current->uuid, uuid) == 0) { if (previous == NULL) { Config.simulators = current->next; free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; free(current); return 1; } else { free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; previous->next = current->next; free(current); current = previous->next; return 1; } } else { previous = current; current = current->next; } } return 0; } /* * SIMULATOR ADD name * SIMULATOR DEL uuid * SIMULATOR LIST * SIMULATOR GET uuid * SIMULATOR PUT uuid */ int cmd_simulator(char *buf) { char *opt, *param, *kwd, *val, ibuf[SS_BUFSIZE]; simulator_list *simulator, *tmps; int rc, rlen, ival; float fval; uuid_t uu; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } param = strtok(NULL, "\0"); if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"SIMULATOR ADD name Add a new Simulator with name"); srv_send((char *)"SIMULATOR DEL uuid Delete Simulator by uuid"); srv_send((char *)"SIMULATOR LIST List all Simulators"); srv_send((char *)"SIMULATOR GET uuid Get Simulator record by uuid"); srv_send((char *)"SIMULATOR PUT uuid Put Simulator record by uuid"); srv_send((char *)"."); return 0; } if (strcmp(opt, (char *)"LIST") == 0) { srv_send((char *)"212 Simulators list follows:"); for (simulator = Config.simulators; simulator; simulator = simulator->next) { srv_send((char *)"%s,%s", simulator->uuid, simulator->name); } srv_send((char *)"."); return 0; } if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 0; } if (strcmp(opt, (char *)"ADD") == 0) { /* * For now, only one simulator is allowed. */ if (Config.simulators) { srv_send((char *)"441 Maximum simulators reached"); return 0; } simulator = (simulator_list *)malloc(sizeof(simulator_list)); simulator->next = NULL; simulator->version = 1; simulator->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, simulator->uuid); simulator->name = xstrcpy(param); simulator->volume_air = 150; simulator->volume_beer = 50; simulator->room_temperature = simulator->air_temperature = simulator->beer_temperature = simulator->s_cool_temp = simulator->s_heat_temp = 20.0; simulator->cooler_temp = -3.0; /* Cooling temperature */ simulator->cooler_time = 720; /* About 12 minutes for the cooler plate */ simulator->cooler_size = 0.8; /* 0.8 square meter cooler plate */ simulator->heater_temp = 150.0; /* Heating temperature */ simulator->heater_time = 3; /* 3 seconds to heat-up */ simulator->heater_size = 0.01; /* 0.01 square meter heater plate */ simulator->heater_state = simulator->cooler_state = 0; simulator->frigo_isolation = 0.002; simulator->s_yeast_heat = 0.0; simulator->s_yeast_started = simulator->s_cool_changed = simulator->s_heat_changed = (int)0; if (Config.simulators == NULL) { Config.simulators = simulator; } else { for (tmps = Config.simulators; tmps; tmps = tmps->next) { if (tmps->next == NULL) { tmps->next = simulator; break; } } } syslog(LOG_NOTICE, "Simulator %s added", simulator->uuid); srv_send((char *)"211 Simulator %s added", simulator->uuid); return 1; } if (strcmp(opt, (char *)"DEL") == 0) { rc = delete_Simulator(param); if (rc) { syslog(LOG_NOTICE, "Simulator %s deleted", param); srv_send((char *)"211 Simulator %s deleted", param); return 1; } else { srv_send((char *)"440 No such simulator"); return 0; } } if (strcmp(opt, (char *)"GET") == 0) { for (simulator = Config.simulators; simulator; simulator = simulator->next) { if (strcmp(simulator->uuid, param) == 0) { srv_send((char *)"213 Simulator record follows:"); srv_send((char *)"NAME,%s", simulator->name); srv_send((char *)"VOLUME_AIR,%d", simulator->volume_air); srv_send((char *)"VOLUME_BEER,%d", simulator->volume_beer); srv_send((char *)"ROOM_TEMPERATURE,%.1f", simulator->room_temperature); srv_send((char *)"AIR_TEMPERATURE,%.3f", simulator->air_temperature); srv_send((char *)"BEER_TEMPERATURE,%.3f", simulator->beer_temperature); srv_send((char *)"COOLER_TEMP,%.1f", simulator->cooler_temp); srv_send((char *)"COOLER_TIME,%d", simulator->cooler_time); srv_send((char *)"COOLER_SIZE,%.3f", simulator->cooler_size); srv_send((char *)"HEATER_TEMP,%.1f", simulator->heater_temp); srv_send((char *)"HEATER_TIME,%d", simulator->heater_time); srv_send((char *)"HEATER_SIZE,%.3f", simulator->heater_size); srv_send((char *)"HEATER_STATE,%d", simulator->heater_state); srv_send((char *)"COOLER_STATE,%d", simulator->cooler_state); srv_send((char *)"FRIGO_ISOLATION,%.3f", simulator->frigo_isolation); srv_send((char *)"."); return 0; } } srv_send((char *)"440 No such simulator"); return 0; } if (strcmp(opt, (char *)"PUT") == 0) { for (simulator = Config.simulators; simulator; simulator = simulator->next) { if (strcmp(simulator->uuid, param) == 0) { while (1) { rlen = srv_recv(ibuf); if (rlen == -1) { return 0; } if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Simulator record"); return 1; } kwd = strtok(ibuf, ",\0"); val = strtok(NULL, "\0"); if (kwd && val) { if (strcmp(kwd, (char *)"NAME") == 0) { if (simulator->name) { if (strcmp(simulator->name, val)) syslog(LOG_NOTICE, "Simulator %s name `%s' to `%s'", simulator->uuid, simulator->name, val); free(simulator->name); } simulator->name = xstrcpy(val); } else if (strcmp(kwd, (char *)"VOLUME_AIR") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->volume_air != ival) syslog(LOG_NOTICE, "Simulator %s volume air %d to %d", simulator->uuid, simulator->volume_air, ival); simulator->volume_air = ival; } } else if (strcmp(kwd, (char *)"VOLUME_BEER") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->volume_beer != ival) syslog(LOG_NOTICE, "Simulator %s volume beer %d to %d", simulator->uuid, simulator->volume_beer, ival); simulator->volume_beer = ival; } } else if (strcmp(kwd, (char *)"ROOM_TEMPERATURE") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->room_temperature != fval) syslog(LOG_NOTICE, "Simulator %s room temperature %.1f to %.1f", simulator->uuid, simulator->room_temperature, fval); simulator->room_temperature = fval; } } else if (strcmp(kwd, (char *)"AIR_TEMPERATURE") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->air_temperature != fval) syslog(LOG_NOTICE, "Simulator %s air temperature %.1f to %.1f", simulator->uuid, simulator->air_temperature, fval); simulator->air_temperature = fval; } } else if (strcmp(kwd, (char *)"BEER_TEMPERATURE") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->beer_temperature != fval) syslog(LOG_NOTICE, "Simulator %s beer temperature %.1f to %.1f", simulator->uuid, simulator->beer_temperature, fval); simulator->beer_temperature = fval; } } else if (strcmp(kwd, (char *)"COOLER_TEMP") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->cooler_temp != fval) syslog(LOG_NOTICE, "Simulator %s cooler temperature %.1f to %.1f", simulator->uuid, simulator->cooler_temp, fval); simulator->cooler_temp = fval; } } else if (strcmp(kwd, (char *)"COOLER_TIME") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->cooler_time != ival) syslog(LOG_NOTICE, "Simulator %s cooler time %d to %d", simulator->uuid, simulator->cooler_time, ival); simulator->cooler_time = ival; } } else if (strcmp(kwd, (char *)"COOLER_SIZE") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->cooler_size != fval) syslog(LOG_NOTICE, "Simulator %s cooler size %.1f to %.1f", simulator->uuid, simulator->cooler_size, fval); simulator->cooler_size = fval; } } else if (strcmp(kwd, (char *)"HEATER_TEMP") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->heater_temp != fval) syslog(LOG_NOTICE, "Simulator %s heater temperature %.1f to %.1f", simulator->uuid, simulator->heater_temp, fval); simulator->heater_temp = fval; } } else if (strcmp(kwd, (char *)"HEATER_TIME") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->heater_time != ival) syslog(LOG_NOTICE, "Simulator %s heater time %d to %d", simulator->uuid, simulator->heater_time, ival); simulator->heater_time = ival; } } else if (strcmp(kwd, (char *)"HEATER_SIZE") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->heater_size != fval) syslog(LOG_NOTICE, "Simulator %s heater size %.1f to %.1f", simulator->uuid, simulator->heater_size, fval); simulator->heater_size = fval; } } else if (strcmp(kwd, (char *)"HEATER_STATE") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->heater_state != ival) syslog(LOG_NOTICE, "Simulator %s heater state %d to %d", simulator->uuid, simulator->heater_state, ival); simulator->heater_state = ival; } } else if (strcmp(kwd, (char *)"COOLER_STATE") == 0) { if (sscanf(val, "%d", &ival) == 1) { if (simulator->cooler_state != ival) syslog(LOG_NOTICE, "Simulator %s cooler state %d to %d", simulator->uuid, simulator->cooler_state, ival); simulator->cooler_state = ival; } } else if (strcmp(kwd, (char *)"FRIGO_ISOLATION") == 0) { if (sscanf(val, "%f", &fval) == 1) { if (simulator->frigo_isolation != fval) syslog(LOG_NOTICE, "Simulator %s frigo isolation %.1f to %.1f", simulator->uuid, simulator->frigo_isolation, fval); simulator->frigo_isolation = fval; } } } } } } } srv_send((char *)"440 No such simulator"); return 0; } srv_send((char *)"504 Subcommand error"); return 0; } #endif int delete_Unit(char *uuid) { units_list *current = Config.units; units_list *previous = NULL; while (current) { if (strcmp(current->uuid, uuid) == 0) { if (previous == NULL) { Config.units = current->next; free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; if (current->air_address) free(current->air_address); current->air_address = NULL; if (current->beer_address) free(current->beer_address); current->beer_address = NULL; if (current->chiller_address) free(current->chiller_address); current->chiller_address = NULL; if (current->heater_address) free(current->heater_address); current->heater_address = NULL; if (current->cooler_address) free(current->cooler_address); current->cooler_address = NULL; if (current->fan_address) free(current->fan_address); current->fan_address = NULL; if (current->light_address) free(current->light_address); current->light_address = NULL; if (current->door_address) free(current->door_address); current->door_address = NULL; if (current->psu_address) free(current->psu_address); current->psu_address = NULL; if (current->profile) free(current->profile); current->profile = NULL; if (current->PID_cool) free(current->PID_cool); current->PID_cool = NULL; if (current->PID_heat) free(current->PID_heat); current->PID_heat = NULL; free(current); return 1; } else { free(current->uuid); current->uuid = NULL; free(current->name); current->name = NULL; if (current->air_address) free(current->air_address); current->air_address = NULL; if (current->beer_address) free(current->beer_address); current->beer_address = NULL; if (current->chiller_address) free(current->chiller_address); current->chiller_address = NULL; if (current->heater_address) free(current->heater_address); current->heater_address = NULL; if (current->cooler_address) free(current->cooler_address); current->cooler_address = NULL; if (current->fan_address) free(current->fan_address); current->fan_address = NULL; if (current->door_address) free(current->door_address); current->door_address = NULL; if (current->light_address) free(current->light_address); current->light_address = NULL; if (current->psu_address) free(current->psu_address); current->psu_address = NULL; if (current->profile) free(current->profile); current->profile = NULL; if (current->PID_cool) free(current->PID_cool); current->PID_cool = NULL; if (current->PID_heat) free(current->PID_heat); current->PID_heat = NULL; previous->next = current->next; free(current); current = previous->next; return 1; } } else { previous = current; current = current->next; } } return 0; } /* * UNIT ADD name * UNIT DEL uuid * UNIT LIST * UNIT GET uuid * UNIT PUT uuid */ int cmd_unit(char *buf) { char *opt, *param = NULL, *kwd, *val, ibuf[SS_BUFSIZE]; units_list *unit, *tmpu; uuid_t uu; int ival, i, rc, rlen; float fval; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); if (opt == NULL) { srv_send((char *)"501 Subcommand missing"); return 0; } param = strtok(NULL, "\0"); if (strcmp(opt, (char *)"HELP") == 0) { srv_send((char *)"100 Help text follows:"); srv_send((char *)"Recognized commands:"); srv_send((char *)"UNIT ADD name Add a new Unit with name"); srv_send((char *)"UNIT DEL uuid Delete Unit by uuid"); srv_send((char *)"UNIT LIST List all Units"); srv_send((char *)"UNIT GET uuid Get Unit record by uuid"); srv_send((char *)"UNIT PUT uuid Put Unit record by uuid"); srv_send((char *)"."); return 0; } if ((strcmp(opt, (char *)"LIST") == 0) && (param == NULL)) { srv_send((char *)"212 Fermenter list follows:"); for (unit = Config.units; unit; unit = unit->next) { srv_send((char *)"%s,%s,%s", unit->uuid, unit->name, UNITMODE[unit->mode]); } srv_send((char *)"."); return 0; } if (param == NULL) { srv_send((char *)"502 Parameter missing"); return 0; } if (strcmp(opt, (char *)"ADD") == 0) { char an[128]; sprintf(an, "unit%d", Config.next_unit); Config.next_unit++; unit = (units_list *)malloc(sizeof(units_list)); unit->next = NULL; unit->version = 1; unit->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, unit->uuid); unit->name = xstrcpy(param); unit->alias = xstrcpy(an); unit->air_address = unit->beer_address = unit->chiller_address = unit->heater_address = unit->cooler_address = \ unit->fan_address = unit->door_address = unit->light_address = \ unit->psu_address = unit->profile = NULL; unit->air_idx = unit->beer_idx = unit->chiller_idx = unit->heater_idx = unit->cooler_idx = unit->fan_idx = \ unit->door_idx = unit->light_idx = unit->psu_idx = 0; unit->volume = unit->prof_peak_abs = unit->prof_peak_rel = 0.0; unit->air_state = unit->beer_state = unit->chiller_state = 1; unit->air_temperature = unit->beer_temperature = unit->chiller_temperature = 20000; unit->beer_set = unit->fridge_set = 20.0; unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = \ unit->light_state = unit->psu_state = unit->prof_state = 0; unit->heater_delay = unit->cooler_delay = unit->fan_delay = 20; /* 5 minutes delay */ unit->light_delay = 1; /* 15 seconds delay */ unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; unit->heater_usage = unit->cooler_usage = unit->fan_usage = unit->light_usage = 0; unit->temp_set_min = 1.0; unit->temp_set_max = 30.0; unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0; unit->prof_percent = 0; unit->PID_cool = (pid_var *)malloc(sizeof(pid_var)); unit->PID_heat = (pid_var *)malloc(sizeof(pid_var)); InitPID(unit->PID_cool, PID_TYPE_COOL); InitPID(unit->PID_heat, PID_TYPE_HEAT); /* * Block main process */ run_pause = TRUE; for (;;) { usleep(100000); if (run_hold) break; } if (Config.units == NULL) { Config.units = unit; } else { for (tmpu = Config.units; tmpu; tmpu = tmpu->next) { if (tmpu->next == NULL) { tmpu->next = unit; break; } } } lcd_buf_reset(); run_pause = FALSE; syslog(LOG_NOTICE, "Unit %s added", unit->uuid); srv_send((char *)"211 Unit %s added", unit->uuid); return 1; } if (strcmp(opt, (char *)"DEL") == 0) { /* * Block main process. */ run_pause = TRUE; for (;;) { usleep(100000); if (run_hold) break; } rc = delete_Unit(param); lcd_buf_reset(); run_pause = FALSE; if (rc) { syslog(LOG_NOTICE, "Unit %s deleted", param); srv_send((char *)"211 Unit %s deleted", param); return 1; } else { srv_send((char *)"440 No such unit"); return 0; } } if (strcmp(opt, (char *)"GET") == 0) { for (unit = Config.units; unit; unit = unit->next) { if (strcmp(param, unit->uuid) == 0) { srv_send((char *)"213 Unit listing follows:"); srv_send((char *)"NAME,%s", unit->name); srv_send((char *)"UUID,%s", unit->uuid); srv_send((char *)"ALIAS,%s", unit->alias); srv_send((char *)"MODE,%s", UNITMODE[unit->mode]); srv_send((char *)"VOLUME,%2f", unit->volume); srv_send((char *)"AIR_ADDRESS,%s", unit->air_address); srv_send((char *)"AIR_STATE,%s", TEMPSTATE[unit->air_state]); srv_send((char *)"AIR_TEMPERATURE,%.3f", unit->air_temperature / 1000.0); srv_send((char *)"AIR_IDX,%d", unit->air_idx); srv_send((char *)"BEER_ADDRESS,%s", MBSE_SS(unit->beer_address)); srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]); srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0); srv_send((char *)"BEER_IDX,%d", unit->beer_idx); srv_send((char *)"CHILLER_ADDRESS,%s", MBSE_SS(unit->chiller_address)); srv_send((char *)"CHILLER_STATE,%s", TEMPSTATE[unit->chiller_state]); srv_send((char *)"CHILLER_TEMPERATURE,%.3f", unit->chiller_temperature / 1000.0); srv_send((char *)"CHILLER_IDX,%d", unit->chiller_idx); srv_send((char *)"HEATER_ADDRESS,%s", unit->heater_address); srv_send((char *)"HEATER_STATE,%d", unit->heater_state); srv_send((char *)"HEATER_DELAY,%d", unit->heater_delay); srv_send((char *)"HEATER_USAGE,%d", unit->heater_usage); srv_send((char *)"HEATER_IDX,%d", unit->heater_idx); if (unit->PID_heat) { srv_send((char *)"PIDH_IMAX,%.1f", unit->PID_heat->iMax); srv_send((char *)"PIDH_IDLERANGE,%.2f", unit->PID_heat->idleRange); srv_send((char *)"PIDH_PGAIN,%.3f", unit->PID_heat->pGain); srv_send((char *)"PIDH_IGAIN,%.3f", unit->PID_heat->iGain); srv_send((char *)"PIDH_DGAIN,%.3f", unit->PID_heat->dGain); srv_send((char *)"PIDH_SV,%.2f", unit->PID_heat->SetP); } srv_send((char *)"COOLER_ADDRESS,%s", unit->cooler_address); srv_send((char *)"COOLER_STATE,%d", unit->cooler_state); srv_send((char *)"COOLER_DELAY,%d", unit->cooler_delay); srv_send((char *)"COOLER_USAGE,%d", unit->cooler_usage); srv_send((char *)"COOLER_IDX,%d", unit->cooler_idx); if (unit->PID_cool) { srv_send((char *)"PIDC_IMAX,%.1f", unit->PID_cool->iMax); srv_send((char *)"PIDC_IDLERANGE,%.2f", unit->PID_cool->idleRange); srv_send((char *)"PIDC_PGAIN,%.3f", unit->PID_cool->pGain); srv_send((char *)"PIDC_IGAIN,%.3f", unit->PID_cool->iGain); srv_send((char *)"PIDC_DGAIN,%.3f", unit->PID_cool->dGain); srv_send((char *)"PIDC_SV,%.2f", unit->PID_cool->SetP); } srv_send((char *)"FAN_ADDRESS,%s", unit->fan_address); srv_send((char *)"FAN_STATE,%d", unit->fan_state); srv_send((char *)"FAN_DELAY,%d", unit->fan_delay); srv_send((char *)"FAN_USAGE,%d", unit->fan_usage); srv_send((char *)"FAN_IDX,%d", unit->fan_idx); srv_send((char *)"LIGHT_ADDRESS,%s", unit->light_address); srv_send((char *)"LIGHT_STATE,%d", unit->light_state); srv_send((char *)"LIGHT_DELAY,%d", unit->light_delay); srv_send((char *)"LIGHT_USAGE,%d", unit->light_usage); srv_send((char *)"LIGHT_IDX,%d", unit->light_idx); srv_send((char *)"DOOR_ADDRESS,%s", unit->door_address); srv_send((char *)"DOOR_STATE,%d", unit->door_state); srv_send((char *)"DOOR_IDX,%d", unit->door_idx); srv_send((char *)"PSU_ADDRESS,%s", unit->psu_address); srv_send((char *)"PSU_STATE,%d", unit->psu_state); srv_send((char *)"PSU_IDX,%d", unit->psu_idx); srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set); srv_send((char *)"BEER_SET,%.1f", unit->beer_set); srv_send((char *)"PROFILE,%s", unit->profile); srv_send((char *)"PROF_STARTED,%d", (int)unit->prof_started); if (unit->prof_state == PROFILE_RUN) { srv_send((char *)"PROF_STATE,%s %d%%", PROFSTATE[unit->prof_state], unit->prof_percent); } else { srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]); } srv_send((char *)"PROF_TARGET_LO,%.3f", unit->prof_target_lo); srv_send((char *)"PROF_TARGET_HI,%.3f", unit->prof_target_hi); srv_send((char *)"PROF_FRIDGE_MODE,%d", unit->prof_fridge_mode); srv_send((char *)"PROF_PEAK_ABS,%.3f", unit->prof_peak_abs); srv_send((char *)"PROF_PEAK_REL,%.3f", unit->prof_peak_rel); srv_send((char *)"PROF_PRIMARY_DONE,%d", (int)unit->prof_primary_done); srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); srv_send((char *)"ALARM,%d", unit->alarm_flag); srv_send((char *)"."); return 0; } } srv_send((char *)"440 No such unit"); return 0; } if (strcmp(opt, (char *)"PUT") == 0) { /* * Block main process */ run_pause = TRUE; for (;;) { usleep(100000); if (run_hold) break; } for (unit = Config.units ; unit; unit = unit->next) { if (strcmp(unit->uuid, param) == 0) { while (1) { unit->mqtt_flag = 0; rlen = srv_recv(ibuf); if (rlen == -1) { run_pause = FALSE; return 0; } if (strlen(ibuf)) { if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Unit record"); run_pause = FALSE; return 1; } kwd = strtok(ibuf, ",\0"); val = strtok(NULL, "\0"); if (kwd) { unit->mqtt_flag = 0; /* * Accept writable data. The client can sent just one line, * but may also sent everything. Simply ignore things we * don't understand. */ if (val && (strcmp(kwd, (char *)"NAME") == 0)) { if (unit->name) { if (strcmp(unit->name, val)) { syslog(LOG_NOTICE, "Fermenter unit %s name `%s' to `%s'", unit->uuid, unit->name, val); } free(unit->name); } unit->name = xstrcpy(val); unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"VOLUME") == 0)) { if (sscanf(val, "%f", &fval) == 1) { if (unit->volume != fval) syslog(LOG_NOTICE, "Fermenter unit %s volume %.3f to %.3f", unit->uuid, unit->volume, fval); unit->volume = fval; } } else if (strcmp(kwd, (char *)"AIR_ADDRESS") == 0) { if (val && unit->air_address && (strcmp(val, unit->air_address))) syslog(LOG_NOTICE, "Fermenter unit %s air address `%s' to `%s'", unit->uuid, unit->air_address, val); if (unit->air_address) { device_count(FALSE, unit->air_address); free(unit->air_address); } if (val) { unit->air_address = xstrcpy(val); device_count(TRUE, unit->air_address); } else unit->air_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"AIR_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->air_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s air idx %d to %d", unit->uuid, unit->air_idx, ival); unit->air_idx = ival; } } else if (strcmp(kwd, (char *)"BEER_ADDRESS") == 0) { if (val && unit->beer_address && (strcmp(val, unit->beer_address))) syslog(LOG_NOTICE, "Fermenter unit %s beer address `%s' to `%s'", unit->uuid, unit->beer_address, val); if (unit->beer_address) { device_count(FALSE, unit->beer_address); free(unit->beer_address); } if (val) { unit->beer_address = xstrcpy(val); device_count(TRUE, unit->beer_address); } else unit->beer_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"BEER_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->beer_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s beer idx %d to %d", unit->uuid, unit->beer_idx, ival); unit->beer_idx = ival; } } else if (strcmp(kwd, (char *)"CHILLER_ADDRESS") == 0) { if (val && unit->chiller_address && (strcmp(val, unit->chiller_address))) syslog(LOG_NOTICE, "Fermenter unit %s chiller address `%s' to `%s'", unit->uuid, unit->chiller_address, val); if (unit->chiller_address) { device_count(FALSE, unit->chiller_address); free(unit->chiller_address); } if (val) { unit->chiller_address = xstrcpy(val); device_count(TRUE, unit->chiller_address); } else unit->chiller_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"CHILLER_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->chiller_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s chiller idx %d to %d", unit->uuid, unit->chiller_idx, ival); unit->chiller_idx = ival; } } else if (strcmp(kwd, (char *)"HEATER_ADDRESS") == 0) { if (val && unit->heater_address && (strcmp(val, unit->heater_address))) syslog(LOG_NOTICE, "Fermenter unit %s heater address `%s' to `%s'", unit->uuid, unit->heater_address, val); if (unit->heater_address) { device_count(FALSE, unit->heater_address); free(unit->heater_address); } if (val) { unit->heater_address = xstrcpy(val); device_count(TRUE, unit->heater_address); } else unit->heater_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"HEATER_STATE") == 0)) { if ((sscanf(val, "%d", &ival) == 1) && ((ival == 0) || (ival == 100))) { if (unit->heater_state != ival) syslog(LOG_NOTICE, "Fermenter unit %s heater state %d to %d", unit->uuid, unit->heater_state, ival); unit->heater_state = ival; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"HEATER_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->heater_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s heater idx %d to %d", unit->uuid, unit->heater_idx, ival); unit->heater_idx = ival; } } else if (val && (strcmp(kwd, (char *)"HEATER_DELAY") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->heater_delay != ival) syslog(LOG_NOTICE, "Fermenter unit %s heater delay %d to %d", unit->uuid, unit->heater_delay, ival); unit->heater_delay = ival; } } else if (strcmp(kwd, (char *)"COOLER_ADDRESS") == 0) { if (val && unit->cooler_address && (strcmp(val, unit->cooler_address))) syslog(LOG_NOTICE, "Fermenter unit %s cooler address `%s' to `%s'", unit->uuid, unit->cooler_address, val); if (unit->cooler_address) { device_count(FALSE, unit->cooler_address); free(unit->cooler_address); } if (val) { unit->cooler_address = xstrcpy(val); device_count(TRUE, unit->cooler_address); } else unit->cooler_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"COOLER_STATE") == 0)) { if ((sscanf(val, "%d", &ival) == 1) && ((ival == 0) || (ival == 100))) { if (unit->cooler_state != ival) syslog(LOG_NOTICE, "Fermenter unit %s cooler state %d to %d", unit->uuid, unit->cooler_state, ival); unit->cooler_state = ival; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"COOLER_DELAY") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->cooler_delay != ival) syslog(LOG_NOTICE, "Fermenter unit %s cooler delay %d to %d", unit->uuid, unit->cooler_delay, ival); unit->cooler_delay = ival; } } else if (val && (strcmp(kwd, (char *)"COOLER_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->cooler_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s cooler idx %d to %d", unit->uuid, unit->cooler_idx, ival); unit->cooler_idx = ival; } } else if (strcmp(kwd, (char *)"FAN_ADDRESS") == 0) { if (val && unit->fan_address && (strcmp(val, unit->fan_address))) syslog(LOG_NOTICE, "Fermenter unit %s fan address `%s' to `%s'", unit->uuid, unit->fan_address, val); if (unit->fan_address) { device_count(FALSE, unit->fan_address); free(unit->fan_address); } if (val) { unit->fan_address = xstrcpy(val); device_count(TRUE, unit->fan_address); } else unit->fan_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"FAN_STATE") == 0)) { if ((sscanf(val, "%d", &ival) == 1) && ((ival == 0) || (ival == 100))) { if (unit->fan_state != ival) syslog(LOG_NOTICE, "Fermenter unit %s fan state %d to %d", unit->uuid, unit->fan_state, ival); unit->fan_state = ival; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"FAN_DELAY") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->fan_delay != ival) syslog(LOG_NOTICE, "Fermenter unit %s fan delay %d to %d", unit->uuid, unit->fan_delay, ival); unit->fan_delay = ival; } } else if (val && (strcmp(kwd, (char *)"FAN_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->fan_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s fan idx %d to %d", unit->uuid, unit->fan_idx, ival); unit->fan_idx = ival; } } else if (strcmp(kwd, (char *)"LIGHT_ADDRESS") == 0) { if (val && unit->light_address && (strcmp(val, unit->light_address))) syslog(LOG_NOTICE, "Fermenter unit %s light address `%s' to `%s'", unit->uuid, unit->light_address, val); if (unit->light_address) { device_count(FALSE, unit->light_address); free(unit->light_address); } if (val) { unit->light_address = xstrcpy(val); device_count(TRUE, unit->light_address); } else unit->light_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"LIGHT_STATE") == 0)) { if ((sscanf(val, "%d", &ival) == 1) && ((ival == 0) || (ival == 100))) { if (unit->light_state != ival) syslog(LOG_NOTICE, "Fermenter unit %s light state %d to %d", unit->uuid, unit->light_state, ival); unit->light_state = ival; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"LIGHT_DELAY") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->light_delay != ival) syslog(LOG_NOTICE, "Fermenter unit %s light delay %d to %d", unit->uuid, unit->light_delay, ival); unit->light_delay = ival; } } else if (val && (strcmp(kwd, (char *)"LIGHT_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->light_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s light idx %d to %d", unit->uuid, unit->light_idx, ival); unit->light_idx = ival; } } else if (strcmp(kwd, (char *)"DOOR_ADDRESS") == 0) { if (val && unit->door_address && (strcmp(val, unit->door_address))) syslog(LOG_NOTICE, "Fermenter unit %s door address `%s' to `%s'", unit->uuid, unit->door_address, val); if (unit->door_address) { device_count(FALSE, unit->door_address); free(unit->door_address); } if (val) { unit->door_address = xstrcpy(val); device_count(TRUE, unit->door_address); } else unit->door_address = NULL; } else if (val && (strcmp(kwd, (char *)"DOOR_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->door_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s door idx %d to %d", unit->uuid, unit->door_idx, ival); unit->door_idx = ival; } } else if (strcmp(kwd, (char *)"PSU_ADDRESS") == 0) { if (val && unit->psu_address && (strcmp(val, unit->psu_address))) syslog(LOG_NOTICE, "Fermenter unit %s psu address `%s' to `%s'", unit->uuid, unit->psu_address, val); if (unit->psu_address) { device_count(FALSE, unit->psu_address); free(unit->psu_address); } if (val) { unit->psu_address = xstrcpy(val); device_count(TRUE, unit->psu_address); } else unit->psu_address = NULL; unit->mqtt_flag |= MQTT_FLAG_DATA; } else if (val && (strcmp(kwd, (char *)"PSU_IDX") == 0)) { if (sscanf(val, "%d", &ival) == 1) { if (unit->psu_idx != ival) syslog(LOG_NOTICE, "Fermenter unit %s psu idx %d to %d", unit->uuid, unit->psu_idx, ival); unit->psu_idx = ival; } } else if (val && (strcmp(kwd, (char *)"MODE") == 0)) { for (i = 0; i < 5; i++) { if (strcmp(val, UNITMODE[i]) == 0) { unit->mqtt_flag |= MQTT_FLAG_DATA; /* Initialize log if the unit is turned on */ if ((unit->mode == UNITMODE_OFF) && (i != UNITMODE_OFF)) { initlog(unit->name); unit->mqtt_flag |= MQTT_FLAG_BIRTH; } else if ((unit->mode != UNITMODE_OFF) && (i == UNITMODE_OFF)) { unit->mqtt_flag |= MQTT_FLAG_DEATH; } syslog(LOG_NOTICE, "Fermenter unit %s mode %s to %s", unit->uuid, UNITMODE[unit->mode], UNITMODE[i]); unit->mode = i; /* Allways turn everything off after a mode change */ unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; device_out(unit->heater_address, unit->heater_state); device_out(unit->cooler_address, unit->cooler_state); device_out(unit->fan_address, unit->fan_state); device_out(unit->light_address, unit->light_state); if (unit->mode == UNITMODE_PROFILE) { /* * Set a sane default until it will be overruled by the * main processing loop. */ unit->prof_target_lo = unit->prof_target_hi = 20.0; unit->prof_fridge_mode = 0; if (unit->profile) { unit->mqtt_flag |= MQTT_FLAG_DATA; } } break; } } } else if (val && (strcmp(kwd, (char *)"FRIDGE_SET") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) { if (unit->fridge_set != fval) syslog(LOG_NOTICE, "Fermenter unit %s fridge temperature %.1f to %.1f", unit->uuid, unit->fridge_set, fval); unit->fridge_set = fval; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"BEER_SET") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) { if (unit->beer_set != fval) syslog(LOG_NOTICE, "Fermenter unit %s beer temperature %.1f to %.1f", unit->uuid, unit->beer_set, fval); unit->beer_set = fval; unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"PIDC_IMAX") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_cool->iMax != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_cool iGain %.1f to %.1f", unit->uuid, unit->PID_cool->iMax, fval); unit->PID_cool->iMax = fval; } } else if (val && (strcmp(kwd, (char *)"PIDC_PGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_cool->pGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_cool pGain %.3f to %.3f", unit->uuid, unit->PID_cool->pGain, fval); unit->PID_cool->pGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDC_DGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_cool->dGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_cool dGain %.3f to %.3f", unit->uuid, unit->PID_cool->dGain, fval); unit->PID_cool->dGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDC_IGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_cool->iGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_cool iGain %.3f to %.3f", unit->uuid, unit->PID_cool->iGain, fval); unit->PID_cool->iGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDC_IDLERANGE") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_cool->idleRange != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_cool idleRange %.2f to %.2f", unit->uuid, unit->PID_cool->idleRange, fval); unit->PID_cool->idleRange = fval; } } else if (val && (strcmp(kwd, (char *)"PIDH_IMAX") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_heat->iMax != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_heat iGain %.1f to %.1f", unit->uuid, unit->PID_heat->iMax, fval); unit->PID_heat->iMax = fval; } } else if (val && (strcmp(kwd, (char *)"PIDH_PGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_heat->pGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_heat pGain %.3f to %.3f", unit->uuid, unit->PID_heat->pGain, fval); unit->PID_heat->pGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDH_DGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_heat->dGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_heat dGain %.3f to %.3f", unit->uuid, unit->PID_heat->dGain, fval); unit->PID_heat->dGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDH_IGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_heat->iGain != fval) syslog(LOG_NOTICE, "Fermenter unit %s PIH_heat iGain %.3f to %.3f", unit->uuid, unit->PID_heat->iGain, fval); unit->PID_heat->iGain = fval; } } else if (val && (strcmp(kwd, (char *)"PIDH_IDLERANGE") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { if (unit->PID_heat->idleRange != fval) syslog(LOG_NOTICE, "Fermenter unit %s PID_heat idleRange %.2f to %.2f", unit->uuid, unit->PID_heat->idleRange, fval); unit->PID_heat->idleRange = fval; } } else if (strcmp(kwd, (char *)"PROFILE") == 0) { if (unit->prof_state == PROFILE_OFF) { /* * Only change profile if it is not active, else drop this one. */ if (unit->profile && val && strcmp(unit->profile, val)) syslog(LOG_NOTICE, "Fermenter unit %s profile name `%s' to `%s'", unit->uuid, unit->profile, val); if (unit->profile) free(unit->profile); if (val) unit->profile = xstrcpy(val); else unit->profile = NULL; /* * Reset all output devices */ unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; device_out(unit->heater_address, unit->heater_state); device_out(unit->cooler_address, unit->cooler_state); device_out(unit->fan_address, unit->fan_state); device_out(unit->light_address, unit->light_state); unit->mqtt_flag |= MQTT_FLAG_DATA; } } else if (val && (strcmp(kwd, (char *)"PROF_STATE") == 0)) { for (i = 0; i < 5; i++) { if (strcmp(val, PROFSTATE[i]) == 0) { switch (i) { case PROFILE_OFF: if (unit->prof_state == PROFILE_DONE) { unit->prof_state = PROFILE_OFF; syslog(LOG_NOTICE, "Fermenter unit %s profile to OFF", unit->uuid); } break; case PROFILE_PAUSE: if (unit->prof_state == PROFILE_RUN) { unit->prof_state = PROFILE_PAUSE; syslog(LOG_NOTICE, "Fermenter unit %s profile PAUSE", unit->uuid); } else if (unit->prof_state == PROFILE_PAUSE) { unit->prof_state = PROFILE_RUN; syslog(LOG_NOTICE, "Fermenter unit %s profile RESUME", unit->uuid); } break; case PROFILE_RUN: if (unit->prof_state == PROFILE_OFF) { unit->prof_state = PROFILE_RUN; unit->prof_started = time(NULL); unit->prof_paused = unit->prof_primary_done = 0; unit->prof_peak_abs = unit->prof_peak_rel = 0.0; syslog(LOG_NOTICE, "Fermenter unit %s profile to RUN", unit->uuid); } break; case PROFILE_DONE: break; /* Command is illegal */ case PROFILE_ABORT: if ((unit->prof_state == PROFILE_RUN) || (unit->prof_state == PROFILE_PAUSE)) { unit->prof_state = PROFILE_OFF; unit->prof_started = 0; syslog(LOG_NOTICE, "Fermenter unit %s profile ABORT", unit->uuid); } break; } unit->mqtt_flag |= MQTT_FLAG_DATA; break; } } } else if (val && (strcmp(kwd, (char *)"TEMP_SET_MIN") == 0)) { if (sscanf(val, "%f", &fval) == 1) { if (unit->temp_set_min != fval) syslog(LOG_NOTICE, "Fermenter unit %s temperature set minimum %.1f to %.1f", unit->uuid, unit->temp_set_min, fval); unit->temp_set_min = fval; } } else if (val && (strcmp(kwd, (char *)"TEMP_SET_MAX") == 0)) { if (sscanf(val, "%f", &fval) == 1) { if (unit->temp_set_max != fval) syslog(LOG_NOTICE, "Fermenter unit %s temperature set maximum %.1f to %.1f", unit->uuid, unit->temp_set_max, fval); unit->temp_set_max = fval; } } if (unit->mqtt_flag) { if (debug) fprintf(stdout, "flag value %d\n", unit->mqtt_flag); if (unit->mqtt_flag & MQTT_FLAG_BIRTH) { publishDBirth(unit); } else { publishDData(unit); } if (unit->mqtt_flag & MQTT_FLAG_DEATH) { publishDDeath(unit); } } } } } } } srv_send((char *)"440 No such unit"); run_pause = FALSE; return 0; } srv_send((char *)"504 Subcommand error"); return 0; } void cmd_server(void) { char buf[SS_BUFSIZE]; int rlen; rlen = srv_recv(buf); if (rlen != -1) { if (strlen(buf)) { /* * Process commands from the client */ if (strncmp(buf, "ARCHIVE", 7) == 0) { cmd_archive(buf); } else if (strncmp(buf, "DEVICE", 6) == 0) { if (cmd_device(buf)) wrconfig(); } else if (strncmp(buf, "GLOBAL", 6) == 0) { if (cmd_global(buf)) wrconfig(); } else if (strncmp(buf, "HELP", 4) == 0) { srv_send((char *)"100 Help text follows"); srv_send((char *)"Recognized commands:"); srv_send((char *)""); // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 srv_send((char *)"ARCHIVE <CMD> [parameters] Archive commands"); srv_send((char *)"ARCHIVE HELP Archive help screen"); srv_send((char *)"DEVICE <CMD> [parameters] Device commands"); srv_send((char *)"DEVICE HELP Device help screen"); srv_send((char *)"GLOBAL <CMD> [parameters] Global commands"); srv_send((char *)"GLOBAL HELP Global help screen"); srv_send((char *)"LIST <CMD> [parameters] List commands"); srv_send((char *)"LIST HELP List help screen"); srv_send((char *)"PING Check if server is alive"); srv_send((char *)"PROFILE <CMD> [parameters] Profile commands"); srv_send((char *)"PROFILE HELP Profile help screen"); #ifdef USE_SIMULATOR srv_send((char *)"SIMULATOR <CMD> [parameters] Simulator commands"); srv_send((char *)"SIMULATOR HELP Simulator help screen"); #endif srv_send((char *)"UNIT <CMD> [parameters] Unit commands"); srv_send((char *)"UNIT HELP Unit help screen"); srv_send((char *)"."); } else if (strncmp(buf, "LIST", 4) == 0) { cmd_list(buf); } else if (strncmp(buf, "PING", 4) == 0) { srv_send((char *)"101 PONG"); } else if (strncmp(buf, "PROFILE", 7) == 0) { if (cmd_profile(buf)) wrconfig(); #ifdef USE_SIMULATOR } else if (strncmp(buf, "SIMULATOR", 9) == 0) { if (cmd_simulator(buf)) wrconfig(); #endif } else if (strncmp(buf, "UNIT", 4) == 0) { if (cmd_unit(buf)) wrconfig(); } else { srv_send((char *)"500 Unknown command"); } } } close(s); } #ifdef HAVE_WIRINGPI_H PI_THREAD (my_server_loop) #else void *my_server_loop(void *threadid) #endif { socklen_t addrlen; int optval = 1; syslog(LOG_NOTICE, "Thread my_server_loop started"); if (debug) fprintf(stdout, "Thread my_server_loop started\n"); memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in)); memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in)); myaddr_in.sin_family = AF_INET; myaddr_in.sin_addr.s_addr = INADDR_ANY; myaddr_in.sin_port = htons(Config.my_port); ls = socket(AF_INET, SOCK_STREAM, 0); if (ls == -1) { syslog(LOG_NOTICE, "Can't create listen socket: %s", strerror(errno)); fprintf(stderr, "Can't create listen socket: %s\n", strerror(errno)); return 0; } if (setsockopt(ls, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) { syslog(LOG_NOTICE, "Can't setsockopt SO_KEEPALIVE socket: %s", strerror(errno)); close(ls); return 0; } if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { syslog(LOG_NOTICE, "Can't setsockopt SO_REUSEADDR socket: %s", strerror(errno)); close(ls); return 0; } if (bind(ls, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) { syslog(LOG_NOTICE, "Can't bind to listen socket: %s", strerror(errno)); close(ls); return 0; } if (listen(ls, 5) == -1) { syslog(LOG_NOTICE, "Can't listen on listen socket: %s", strerror(errno)); close(ls); return 0; } syslog(LOG_NOTICE, "listen socket created %d", ls); /* * Loop forever until the external shutdown variable is set. */ for (;;) { addrlen = sizeof(struct sockaddr_in); /* * This call will block until a new connection * arrives. Then it will return the address of * the connecting peer, and a new socket * descriptor, s, for that connection. */ s = accept(ls, (struct sockaddr *)&peeraddr_in, &addrlen); if (s == -1) { syslog(LOG_NOTICE, "my_server_loop accept failed %s", strerror(errno)); if (debug) fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno)); return 0; } cmd_server(); if (my_shutdown) { syslog(LOG_NOTICE, "Thread my_server_loop stopped"); if (debug) fprintf(stdout, "Thread my_server_loop stopped\n"); return 0; } } }