thermferm/units.c

Sun, 13 Jul 2014 17:31:45 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 13 Jul 2014 17:31:45 +0200
changeset 106
1bd9a16f5061
parent 101
1302abe92eb1
child 164
f16def8472ba
permissions
-rw-r--r--

Added .h files

/*****************************************************************************
 * Copyright (C) 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 "thermferm.h"
#include "units.h"
#include "xutil.h"


extern int		debug;
extern sys_config	Config;
extern int		my_shutdown;

extern const char	UNITMODE[5][8];



int read_w1_28(char *address, int *val)
{
    char 	*device, line[60], *p = NULL;
    FILE	*fp;
    int		rc = 0;

    device = xstrcpy((char *)"/sys/bus/w1/devices/");
    device = xstrcat(device, address);
    device = xstrcat(device, (char *)"/w1_slave");

    /*
     * Read sensor data
     */
    if ((fp = fopen(device, "r"))) {
	/*
	 * The output looks like:
	 * 72 01 4b 46 7f ff 0e 10 57 : crc=57 YES
	 * 72 01 4b 46 7f ff 0e 10 57 t=23125
	 */
	fgets(line, 50, fp);
	line[strlen(line)-1] = '\0';
	if ((line[36] == 'Y') && (line[37] == 'E')) {
	    /*
	     * CRC is Ok, continue
	     */
	    fgets(line, 50, fp);
	    line[strlen(line)-1] = '\0';
	    strtok(line, (char *)"=");
	    p = strtok(NULL, (char *)"=");
	    rc = sscanf(p, "%d", val);
	    if (rc != 1) {
		syslog(LOG_NOTICE, "sensor %s data parse error", address);
		rc = 3;
	    } else {
		rc = 0;
	    }
	} else {
	    syslog(LOG_NOTICE, "sensor %s CRC error", address);
	    rc = 1;
	}
	fclose(fp);
    } else {
	syslog(LOG_NOTICE, "sensor %s is missing", address);
	rc = 2;
    }

    free(device);
    device = NULL;

    return rc;
}



#ifdef HAVE_WIRINGPI_H
PI_THREAD (my_units_loop)
#else
void *my_units_loop(void *threadid)
#endif
{
    units_list		*unit;
    int			rc, temp, deviation;

    /*
     * Initialize units for processing
     */
    for (unit = Config.units; unit; unit = unit->next) {
	/*
	 * Safety, turn everything off
	 */
	unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = 0;
	if (unit->profile && (int)unit->prof_started && (unit->mode == UNITMODE_PROFILE)) {
	    syslog(LOG_NOTICE, "Starting unit %s profile %s", unit->name, unit->profile);
	} else if (unit->mode == UNITMODE_BEER) {
	    syslog(LOG_NOTICE, "Starting unit %s beer cooler at %.1f degrees", unit->name, unit->beer_set);
	} else if (unit->mode == UNITMODE_FRIDGE) {
	    syslog(LOG_NOTICE, "Starting unit %s as refridgerator at %.1f degrees", unit->name, unit->fridge_set);
	} else if (unit->mode == UNITMODE_NONE) {
	    syslog(LOG_NOTICE, "Starting unit %s in inactive state", unit->name);
	} else {
	    syslog(LOG_NOTICE, "Starting unit %s in off state", unit->name);
	}
    }

    syslog(LOG_NOTICE, "Thread my_units_loop started");
    if (debug)
	fprintf(stdout, "Thread my_units_loop started\n");

    /*
     * Loop forever until the external shutdown variable is set.
     */
    for (;;) {

	if (my_shutdown)
	    break;

    	/*
    	 * Update the state of all fermenter units
    	 */
    	for (unit = Config.units; unit; unit = unit->next) {

	    if (my_shutdown)
		break;

	    if (unit->air_address) {
		rc = read_w1_28(unit->air_address, &temp);
		if (rc == 0) {
		    /*
		     * It is possible to have read errors or extreme values.
		     * This can happen with bad connections so we compare the
		     * value with the previous one. If the difference is too
		     * much, we don't send that value. That also means that if
		     * the next value is ok again, it will be marked invalid too.
		     * Maximum error is 20 degrees for now.
		     */
		    deviation = 20000;
		    if ((unit->air_temperature == 0) ||
			(unit->air_temperature && (temp > (int)unit->air_temperature - deviation) && (temp < ((int)unit->air_temperature + deviation)))) {
			unit->air_temperature = temp;
			unit->air_state = 0;
		    } else {
			syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->air_temperature, temp);
			if (debug) {
			    fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->air_temperature, temp);
			}
		    }
		} else if (rc == 2) {
		    unit->air_state = 1;
		} else {
		    unit->air_state = 2;
		}
	    }
	    if (my_shutdown)
		break;

	    if (unit->beer_address) {
		rc = read_w1_28(unit->beer_address, &temp);
		if (rc == 0) {
		    deviation = 20000;
		    if ((unit->beer_temperature == 0) ||
		    	(unit->beer_temperature && (temp > (int)unit->beer_temperature - deviation) && (temp < ((int)unit->beer_temperature + deviation)))) {
		    	unit->beer_temperature = temp;
			unit->beer_state = 0;
		    } else {
		    	syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->beer_temperature, temp);
		    	if (debug) {
			    fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->beer_temperature, temp);
		    	}
		    }
		} else if (rc == 2) {
		    unit->beer_state = 1;
		} else {
		    unit->beer_state = 2;
		}
	    }
	    if (my_shutdown)
		break;


    	}
	usleep(10000);
    }

    /*
     * Stop units processing in a neat way
     */
    for (unit = Config.units; unit; unit = unit->next) {
	/*
	 * Turn everything off
	 */
	unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = 0;
	syslog(LOG_NOTICE, "Stopped unit %s mode %s", unit->name, UNITMODE[unit->mode]);
    }

    syslog(LOG_NOTICE, "Thread my_units_loop stopped");
    if (debug)
	fprintf(stdout, "Thread my_units_loop stopped\n");
    return 0;
}

mercurial