# HG changeset patch # User Michiel Broek # Date 1404509873 -7200 # Node ID b759f814469d4ff2500f80867d526c7610295e66 # Parent 116226a8c70a3e845b4566867227b4b286d95baf Added units processing thread diff -r 116226a8c70a -r b759f814469d thermferm/Makefile --- a/thermferm/Makefile Fri Jul 04 20:00:19 2014 +0200 +++ b/thermferm/Makefile Fri Jul 04 23:37:53 2014 +0200 @@ -63,4 +63,5 @@ xutil.o: thermferm.h server.o: thermferm.h rdconfig.o: thermferm.h +units.o: thermferm.h # End of generated dependencies diff -r 116226a8c70a -r b759f814469d thermferm/thermferm.c --- a/thermferm/thermferm.c Fri Jul 04 20:00:19 2014 +0200 +++ b/thermferm/thermferm.c Fri Jul 04 23:37:53 2014 +0200 @@ -41,7 +41,7 @@ #endif int lcdupdate; #ifndef HAVE_WIRINGPI_H -pthread_t threads[2]; +pthread_t threads[3]; #endif int server(void); @@ -267,6 +267,20 @@ #endif } +#ifdef HAVE_WIRINGPI_H + rc = piThreadCreate(my_units_loop); +#else + rc = pthread_create(&threads[t], NULL, my_units_loop, (void *)t ); +#endif + if (rc) { + fprintf(stderr, "my_units_loop thread didn't start rc=%d\n", rc); + syslog(LOG_NOTICE, "my_units_loop thread didn't start rc=%d", rc); +#ifndef HAVE_WIRINGPI_H + } else { + t++; +#endif + } + snprintf(buf, 1023, "tempA,tempB"); logger((char *)"thermferm.log", (char *)"thermferm", buf); diff -r 116226a8c70a -r b759f814469d thermferm/thermferm.h --- a/thermferm/thermferm.h Fri Jul 04 20:00:19 2014 +0200 +++ b/thermferm/thermferm.h Fri Jul 04 23:37:53 2014 +0200 @@ -67,9 +67,9 @@ char *name; /* friendly name */ float volume; /* Volume of this unit */ char *air_address; /* DS18B20 address */ - float air_temp; /* Air temperature */ + int air_temp; /* Air temperature * 1000 */ char *beer_address; /* DS18B20 address */ - float beer_temp; /* Beer temperature */ + int beer_temp; /* Beer temperature * 1000 */ char *io1_address; /* DS2413 address */ char *io2_address; /* DS2413 address */ int heater_available; /* Heater available */ @@ -230,6 +230,12 @@ void *my_server_loop(void *); #endif +#ifdef HAVE_WIRINGPI_H +PI_THREAD (my_units_loop); +#else +void *my_units_loop(void *); +#endif + #endif diff -r 116226a8c70a -r b759f814469d thermferm/units.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermferm/units.c Fri Jul 04 23:37:53 2014 +0200 @@ -0,0 +1,200 @@ +/***************************************************************************** + * Copyright (C) 2014 + * + * Michiel Broek + * + * 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" + + +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 { + 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 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) { + if (read_w1_28(unit->air_address, &temp) == 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_temp == 0) || + (unit->air_temp && (temp > (int)unit->air_temp - deviation) && (temp < ((int)unit->air_temp + deviation)))) { + unit->air_temp = temp; + } else { + syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->air_temp, temp); + if (debug) { + fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->air_temp, temp); + } + } + } + } + if (my_shutdown) + break; + + if (unit->beer_address) { + if (read_w1_28(unit->beer_address, &temp) == 0) { + deviation = 20000; + if ((unit->beer_temp == 0) || + (unit->beer_temp && (temp > (int)unit->beer_temp - deviation) && (temp < ((int)unit->beer_temp + deviation)))) { + unit->beer_temp = temp; + } else { + syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->beer_temp, temp); + if (debug) { + fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->beer_temp, temp); + } + } + } + } + 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; +} + +