thermferm/server.c

Thu, 24 Jul 2014 23:11:28 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 24 Jul 2014 23:11:28 +0200
changeset 132
8bd209d1c020
parent 131
528dc0bb81ab
child 133
345307762220
permissions
-rw-r--r--

Added some profile commands to the server. Profile names can be changed from the web interface. Removed obsolete commands.

/*****************************************************************************
 * Copyright (C) 2008-2014
 *   
 * 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 EC-65K; 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 "server.h"
#include "xutil.h"


extern int		my_shutdown;
extern int		debug;
extern char		*current_unit;
#ifdef HAVE_WIRINGPI_H
extern int		lcdHandle;
extern unsigned char	lcdbuf[MAX_LCDS][20][4];
#endif
extern sys_config       Config;
extern const char	UNITMODE[5][8];
extern const char	UNITmode[5];
extern const char	TEMPSTATE[3][8];

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


float			cs_heatEstimator = 0.2;
float			cs_coolEstimator = 5;
float			cv_beerDiff = 0.0;



/*
 * 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;
}



/*
 * ADD PROFILE name
 * ADD UNIT name
 */
int unit_add(char *buf)
{
    units_list		*unit, *tmpu;
    profiles_list	*profile, *tmpp;
    uuid_t		uu;
    char		*opt, *param;

    opt = strtok(buf, " \0");
    opt = strtok(NULL, " \0");
    if (opt == NULL) {
	srv_send((char *)"501 Subcommand missing");
	return 1;
    }

    param = strtok(NULL, "\0");
    if (param == NULL) {
	srv_send((char *)"501 Parameter missing");
	return 1;
    }

    if (debug)
	fprintf(stdout, "opt: '%s' param: '%s'\n", MBSE_SS(opt), MBSE_SS(param));

    if (strcmp(opt, (char *)"PROFILE") == 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->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\" with uuid %s added", param, profile->uuid);
	srv_send((char *)"211 Profile \"%s\" with uuid %s added", param, profile->uuid);
	return 0;

    } else if (strcmp(opt, (char *)"UNIT") == 0) {
    	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);
	if (current_unit)
	    free(current_unit);
	current_unit = xstrcpy(unit->uuid);
    	unit->name = xstrcpy(param);
    	unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL;
    	unit->volume = 0.0;
	unit->air_state = unit->beer_state = 1;
    	unit->heater_available = unit->cooler_available = unit->fan_available = FALSE;
    	unit->air_temperature = unit->beer_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->prof_state = 0;
    	unit->temp_set_min = 1.0;
    	unit->temp_set_max = 30.0;
    	unit->idle_rangeH = 1.0;
    	unit->idle_rangeL = -1.0;
    	unit->prof_started = (time_t)0;

    	if (Config.units == NULL) {
	    Config.units = unit;
    	} else {
	    for (tmpu = Config.units; tmpu; tmpu = tmpu->next) {
	    	if (tmpu->next == NULL) {
		    tmpu->next = unit;
		    break;
	    	}
	    }
    	}

    	syslog(LOG_NOTICE, "Unit with uuid %s added", unit->uuid);
    	srv_send((char *)"211 Unit with uuid %s added", unit->uuid);
    	return 0;
    }

    srv_send((char *)"502 Unknown command option");
    return 1;
}



/*
 * LIST
 * LIST BUS
 * LIST LOG
 * LIST PROFILES
 * LIST UNIT
 */
int cmd_list(char *buf)
{
    char		*opt, *filename, *p, q[2], buffer[256];
    units_list		*unit;
    profiles_list	*profile;
    prof_step		*step;
    int			j, ref;
    DIR			*fd;
    FILE		*fp;
    struct dirent	*de;

    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 *)"BUS") == 0) {
	/*
	 * 1-wire bus
	 */
	if ((fd = opendir((char *)"/sys/bus/w1/devices"))) {
	    srv_send((char *)"212 1-wire bus devices:");
	    while ((de = readdir(fd))) {
		if (de->d_name[0] != '.') {
		    ref = 0;
		    if (strncmp(de->d_name, (char *)"w1", 2) == 0) {
			srv_send((char *)"%s,0,NA,System device", de->d_name);
		    } else if (strncmp(de->d_name, (char *)"10", 2) == 0) {
			if (Config.air_address && (strcmp(de->d_name, Config.air_address) == 0))
			    ref++;
			for (unit = Config.units; unit; unit = unit->next) {
			    if (unit->air_address && (strcmp(de->d_name, unit->air_address) == 0))
				ref++;
			    if (unit->beer_address && (strcmp(de->d_name, unit->beer_address) == 0))
				ref++;
			}
			srv_send((char *)"%s,%d,18S20,Digital thermometer", de->d_name, ref);
		    } else if (strncmp(de->d_name, (char *)"28", 2) == 0) {
			if (Config.air_address && (strcmp(de->d_name, Config.air_address) == 0))
			    ref++;
			for (unit = Config.units; unit; unit = unit->next) {
			    if (unit->air_address && (strcmp(de->d_name, unit->air_address) == 0))
				ref++;
			    if (unit->beer_address && (strcmp(de->d_name, unit->beer_address) == 0))
				ref++;
			}
			srv_send((char *)"%s,%d,18B20,Digital thermometer", de->d_name, ref);
		    } else if (strncmp(de->d_name, (char *)"29", 2) == 0) {
			for (unit = Config.units; unit; unit = unit->next) {
			    if (unit->io1_address && (strncmp((char *)"29", unit->io1_address, 2) == 0))
				ref++;
			    if (unit->io2_address && (strncmp((char *)"29", unit->io2_address, 2) == 0))
				ref++;
			}
			srv_send((char *)"%s,%d,2408,8 Channel addressable switch/LCD", de->d_name, ref);
		    } else if (strncmp(de->d_name, (char *)"3a", 2) == 0) {
			for (unit = Config.units; unit; unit = unit->next) {
			    if (unit->io1_address && (strncmp((char *)"3a", unit->io1_address, 2) == 0))
				ref++;
			    if (unit->io2_address && (strncmp((char *)"3a", unit->io2_address, 2) == 0))
				ref++;
			}
			srv_send((char *)"%s,%d,2413,Dual channel addressable switchs", de->d_name, ref);
		    } else {
			srv_send((char *)"%s,0,NA,Unknown device", de->d_name);
		    }
		}
	    }
	    srv_send((char *)".");
	    closedir(fd);
	    return 0;
	} else {
	    srv_send((char *)"503 directory /sys/bus/w1/devices: %s", strerror(errno));
	    return 1;
	}

    } else if (strcmp(opt, (char *)"LOG") == 0) {
	/*
	 * Get the logfile data and emit only one line per hour.
	 */
	if (current_unit == NULL) {
	    srv_send((char *)"401 No fermenter unit selected");
	    return 1;
	}

	q[0] = q[1] = 'a';
	for (unit = Config.units; unit; unit = unit->next) {
	    if (strcmp(current_unit, 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"))) {
	    while (fgets(buffer, sizeof(buffer)-1, fp) != NULL) {
		buffer[strlen(buffer) -1] = '\0';
		p = buffer + 17;
		if (strncmp(p, (char *)"Mode", 4)) {
		    if ((q[0] != buffer[11]) || (q[1] != buffer[12])) {
			q[0] = buffer[11];
			q[1] = buffer[12];
		    	srv_send(buffer);
		    }
		}
	    }
	}
	free(filename);
	filename = NULL;
	srv_send((char *)".");
	return 0;

    } else if (strcmp(opt, (char *)"PROFILES") == 0) {
	/*
	 * Fermenting profiles
	 */
	srv_send((char *)"212 profiles:");
	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", profile->uuid, profile->name, j);
	}
	srv_send((char *)".");
	return 0;

    } else if (strcmp(opt, (char *)"UNIT") == 0) {
	/*
	 * List configured and selected fermenter unit
	 */
	if (current_unit == NULL) {
	    srv_send((char *)"401 No fermenter unit selected");
	    return 1;
	}

	srv_send((char *)"213 Unit %s listing follows:", current_unit);
	for (unit = Config.units; unit; unit = unit->next) {
	    if (strcmp(current_unit, unit->uuid) == 0) {
		srv_send((char *)"NAME,%s", unit->name);
		srv_send((char *)"UUID,%s", unit->uuid);
		if (unit->air_address) {
		    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);
		}
		if (unit->beer_address) {
		    srv_send((char *)"BEER_ADDRESS,%s", unit->beer_address);
		    srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]);
		    srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0);
		}
		if (unit->io1_address) {
		    srv_send((char *)"IO1_ADDRESS,%s", unit->io1_address);
		}
		if (unit->io2_address) {
		    srv_send((char *)"IO2_ADDRESS,%s", unit->io2_address);
		}
		if (unit->heater_available) {
		    srv_send((char *)"HEATER_AVAILABLE,%s", unit->heater_available);
		}
		if (unit->cooler_available) {
		    srv_send((char *)"COOLER_AVAILABLE,%s", unit->cooler_available);
		}
		if (unit->fan_available) {
		    srv_send((char *)"FAN_AVAILABLE,%s", unit->fan_available);
		}
		srv_send((char *)"MODE,%s", UNITMODE[unit->mode]);
		srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set);
		srv_send((char *)"BEER_SET,%.1f", unit->beer_set);
		if (unit->profile) {
		    srv_send((char *)"PROFILE,%s", unit->profile);
		}
		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 *)"IDLE_RANGE_L,%.1f", unit->idle_rangeL);
		srv_send((char *)"IDLE_RANGE_H,%.1f", unit->idle_rangeH);
	    }
	}
	srv_send((char *)".");
	return 0;
    }

    srv_send((char *)"502 Unknown command option");
    return 1;
}



/*
 * Set new operating mode
 * MODE OFF|NONE|BEER|FRIDGE|PROFILE
 */
int cmd_mode(char *buf)
{
    return 1;
}



/*
 * PROFILE		List profile status of current unit
 * PROFILE uuid,name	Rename profile name
 */
int cmd_profile(char *buf)
{
    char		*opt, *uuid, *param;
    profiles_list	*profile;
    units_list		*unit;

    opt = strtok(buf, " \0");
    opt = strtok(NULL, "\0");

    if (opt == NULL) {
	/*
	 * Profile status of current unit
	 */
	if (current_unit == NULL) {
	    srv_send((char *)"401 No fermenter unit selected");
	    return 1;
	}
	for (unit = Config.units; unit; unit = unit->next) {
	    if (strcmp(current_unit, unit->uuid) == 0)
		break;
	}

	if (unit->profile == NULL) {
	    srv_send((char *)"441 Unit has no profile");
	    return 1;
	}
	if (unit->mode != UNITMODE_PROFILE) {
	    srv_send((char *)"442 Unit is not using a profile");
	    return 1;
	}
	srv_send((char *)"241 Profile status follows:");


	srv_send((char *)".");
	return 1;

    } else {
	/*
	 * uuid,name rename profile
	 */
	uuid = strtok(opt, ",");
	param = strtok(NULL, "\0");
	fprintf(stdout, "uuid: '%s' param: '%s'\n", uuid, param);
	for (profile = Config.profiles; profile; profile = profile->next) {
	    if (strcmp(profile->uuid, uuid) == 0) {
		syslog(LOG_NOTICE, "Profile %s rename from '%s' to '%s'", uuid, profile->name, param);
		if (profile->name)
		    free(profile->name);
		profile->name = xstrcpy(param);
		srv_send((char *)"240 Profile updated");
		return 0;
	    }
	}
	srv_send((char *)"440 No such profile");
	return 1;
    }

    srv_send((char *)"502 Unknown command option");
    return 1;
}



/*
 * SET BEER float
 * SET FRIDGE float
 * SET VOLUME float
 * SET IDLE_LOW float
 * SET IDLE_HIGH float
 * SET TEMP_MIN float
 * SET TEMP_MAX float
 * SET NAME string
 * SET PROFILE string
 */
int cmd_set(char *buf)
{
    char                *opt, *param;
    units_list          *unit;
    profiles_list	*profile;
    int                 rc;
    float		fval;

    opt = strtok(buf, " \0");
    opt = strtok(NULL, " \0");
    if (opt == NULL) {
	srv_send((char *)"501 Subcommand missing");
	return 1;
    }

    param = strtok(NULL, "\0");
    if (param == NULL) {
	srv_send((char *)"501 Parameter missing");
	return 1;
    }

    rc = sscanf(param, "%f", &fval);

    if (debug)
	fprintf(stdout, "opt='%s' param='%s' rc=%d fval=%.1f\n", opt, param, rc, fval);

    /*
     * Commands below need a selected unit
     */
    if (current_unit == NULL) {
	srv_send((char *)"401 No fermenter unit selected");
	return 1;
    }

    for (unit = Config.units; unit; unit = unit->next) {
	if (strcmp(current_unit, unit->uuid) == 0)
	    break;
    }

    /*
     * If a valid parameter float value
     */
    if (rc == 1) {
	if (strcmp(opt, (char *)"BEER") == 0) {
	    if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) {
	    	unit->beer_set = fval;
	    	srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval);
	    	return 0;
	    } else {
		srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max);
		return 1;
	    }
	} else if (strcmp(opt, (char *)"FRIDGE") == 0) {
	    if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) {
	    	unit->fridge_set = fval;
	    	srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval);
	    	return 0;
	    } else {
		srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max);
		return 1;
	    }
	} else if (strcmp(opt, (char *)"VOLUME") == 0) {
	    /*
	     * Must fit in a 2 TEU container
	     */
	    if ((fval >= 0.0) && (fval <=  77020.0)) {
	    	unit->volume = fval;
	    	srv_send((char *)"214 Unit %s VOLUME set to %.1f", current_unit, fval);
	    	return 0;
	    } else {
		srv_send((char *)"510 New volume not between 0 and 77020");
		return 1;
	    }
	} else if (strcmp(opt, (char *)"IDLE_LOW") == 0) {
	    if ((fval >= -5.0) && (fval <=  -0.1)) {
		unit->idle_rangeL = fval;
		srv_send((char *)"214 Unit %s IDLE_LOW set to %.1f", current_unit, fval);
		return 0;
	    } else {
		srv_send((char *)"510 New value not between -5.0 and -0.1");
		return 1;
	    }
	} else if (strcmp(opt, (char *)"IDLE_HIGH") == 0) {
	   if ((fval >= 0.1) && (fval <=  5.0)) {
		unit->idle_rangeH = fval;
		srv_send((char *)"214 Unit %s IDLE_HIGH set to %.1f", current_unit, fval);
		return 0;
	    } else {
		srv_send((char *)"510 New value not between -5.0 and -0.1");
		return 1;
	    }
	} else if (strcmp(opt, (char *)"TEMP_MIN") == 0) {
	    if ((fval >= -2.0) && (fval <= 35.0) && (fval < unit->temp_set_max)) {
		unit->temp_set_min = fval;
		srv_send((char *)"214 Unit %s TEMP_MIN set to %.1f", current_unit, fval);
		return 0;
	    } else {
		srv_send((char *)"510 New value not between -2.0 and 35.0 and lower then TEMP_MAX");
		return 1;
	    }
	} else if (strcmp(opt, (char *)"TEMP_MAX") == 0) {
	    if ((fval >= -2.0) && (fval <= 35.0) && (fval > unit->temp_set_min)) {
		unit->temp_set_max = fval;
		srv_send((char *)"214 Unit %s TEMP_MAX set to %.1f", current_unit, fval);
		return 0;
	    } else {
		srv_send((char *)"510 New value not between -2.0 and 35.0 and higher then TEMP_MIN");
		return 1;
	    }
	}
    }

    /*
     * Set new unit or beer name
     */
    if (strcmp(opt, (char *)"NAME") == 0) {
	if (unit->name)
	    free(unit->name);
	unit->name = xstrcpy(param);
	srv_send((char *)"214 Unit %s NAME set to '%s'", current_unit, param);
	// TODO: change logfile name
	return 0;
    } else if (strcmp(opt, (char *)"PROFILE") == 0) {
	/*
	 * Check for active profile, already selected etc.
	 */
	if (unit->profile && (unit->mode == UNITMODE_PROFILE)) {
	    srv_send((char *)"541 Cannot change profile while a profile is active");
	    return 1;
	}
	if (unit->profile && (strcmp(unit->profile, param) == 0)) {
	    srv_send((char *)"542 Profile already set");
	    return 1;
	}
	for (profile = Config.profiles; profile; profile = profile->next) {
	    if (strcmp(profile->uuid, param) == 0) {
		if (unit->profile)
		    free(unit->profile);
		unit->profile = xstrcpy(param);
		srv_send((char *)"242 Unit profile changed to %s", param);
		return 0;
	    }
	}
	srv_send((char *)"543 Invalid profile");
	return 1;
    }

    srv_send((char *)"502 Unknown command option");
    return 1;
}



/*
 * UNIT uuid
 */
int cmd_unit(char *buf)
{
    char                *opt;
    units_list          *tmp;

    opt = strtok(buf, " \0");
    opt = strtok(NULL, " \0");

    if (opt == NULL) {
	srv_send((char *)"501 Parameter missing");
	return 1;
    }

    if (strlen(opt) == 36) {
	/*
	 * Search using uuid
	 */
	for (tmp = Config.units; tmp; tmp = tmp->next) {
	    if (strcmp(opt, tmp->uuid) == 0) {
		srv_send((char *)"210 Unit %s selected", tmp->uuid);
		if (current_unit)
		    free(current_unit);
		current_unit = xstrcpy(tmp->uuid);;
		return 0;
	    }
	}
	srv_send((char *)"410 No such unit");
	return 1;
    }

    srv_send((char *)"502 Unknown command option");
    return 1;
}



void cmd_server(void)
{
    char                buf[SS_BUFSIZE];
    int                 i, rlen;
    socklen_t           fromlen;
#ifdef HAVE_WIRINGPI_H
    int			j;
#endif

    memset((char *)&buf, 0, SS_BUFSIZE);
    fromlen = sizeof(peeraddr_in);
    rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen);
    if (rlen == -1) {
	syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno));
    } else {		    
	for (i = 0; i < strlen(buf); i++) {
	    if (buf[i] == '\n')
		buf[i] = '\0';
	    if (buf[i] == '\r')
	    	buf[i] = '\0';
	}
	for (i = strlen(buf) -1; i > 0; i--) {
	    if (buf[i] == ' ')
		buf[i] = '\0';
	    else
		break;
	}
	if (strlen(buf)) {
	    if (debug) {
		syslog(LOG_NOTICE, "recv: \"%s\"", buf);
		fprintf(stdout, "recv: \"%s\"\n", buf);
	    }

	    /*
	     * Process commands from the client
	     */
	    if (strncmp(buf, "ADD", 3) == 0) {
		if (unit_add(buf) == 0)
		    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 *)"ADD PROFILE name              Add a new profile with \"name\"");
		srv_send((char *)"ADD UNIT name                 Add a new unit with \"name\"");
//		srv_send((char *)"DEL PROFILE uuid              Delete profile with uuid");
//		srv_send((char *)"DEL UNIT uuid                 Delete unit with uuid");
		srv_send((char *)"LCD                           Get LCD screen (allways 4 rows of 20 characters)");
		srv_send((char *)"LIST                          List all fermenter units");
		srv_send((char *)"LIST BUS                      List 1-wire bus");
		srv_send((char *)"LIST LOG                      List logfile data in 1 hour lines");
		srv_send((char *)"LIST PROFILES                 List available profiles");
		srv_send((char *)"LIST UNIT                     List fermenter unit");
		srv_send((char *)"MODE OFF|NONE|BEER|FRIDGE|PROFILE");
//		srv_send((char *)"PROFILE                       Profile status of current unit");
		srv_send((char *)"PROFILE uuid,name             Profile rename");
		srv_send((char *)"SET BEER val                  Set beer temperature");
		srv_send((char *)"SET FRIDGE val                Set fridge temperature");
		srv_send((char *)"SET IDLE_LOW val              Set idle temperature low (-5.0 .. -0.1)");
		srv_send((char *)"SET IDLE_HIGH val             Set idle temperature high (0.1 .. 5.0)");
		srv_send((char *)"SET NAME name                 Set name or beername for the unit");
		srv_send((char *)"SET PROFILE uuid              Set unit profile");
//		srv_send((char *)"SET PROFILE start|stop|pause  Profile start, stop or pause");
		srv_send((char *)"SET TEMP_MIN val              Set unit minimum temperature");
		srv_send((char *)"SET TEMP_MAX val              Set unit maximum temperature");
		srv_send((char *)"SET VOLUME val                Set unit volume");
		srv_send((char *)"UNIT uuid                     Select unit by uuid");
		srv_send((char *)".");
	    } else if (strncmp(buf, "LCD", 3) == 0) {
#ifdef HAVE_WIRINGPI_H
		srv_send((char *)"201 information follows");
		for (j = 0; j < 4; j++) {
		    sprintf(obuf, "                   ");
		    obuf[20] = '\0';
		    for (i = 0; i < 20; i++)
		    	obuf[i]  = lcdbuf[lcdHandle][i][j];
		    srv_send(obuf);
		}
		srv_send((char *)".");
#else
		srv_send((char *)"403 LCD not available");
#endif
	    } else if (strncmp(buf, "LIST", 4) == 0) {
		cmd_list(buf);
	    } else if (strncmp(buf, "MODE", 4) == 0) {
		cmd_mode(buf);
	    } else if (strncmp(buf, "PROFILE", 7) == 0) {
		if (cmd_profile(buf) == 0)
		    wrconfig();
	    } else if (strncmp(buf, "SET", 3) == 0) {
		if (cmd_set(buf) == 0)
		    wrconfig();
	    } else if (strncmp(buf, "UNIT", 4) == 0) {
		cmd_unit(buf);
	    } else {
		if (debug)
		    fprintf(stdout, "unknown command \"%s\"\n", buf);
		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);
    if (debug)
	fprintf(stdout, "listen socket created %d\n", 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;
	}

    }
}

mercurial