Added units processing thread

Fri, 04 Jul 2014 23:37:53 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 04 Jul 2014 23:37:53 +0200
changeset 93
b759f814469d
parent 92
116226a8c70a
child 94
38ee038f4cec

Added units processing thread

thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
thermferm/units.c file | annotate | diff | comparison | revisions
--- 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
--- 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);
 
--- 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
 
--- /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 <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"
+
+
+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;
+}
+
+

mercurial