diff -r dafbbd5e9922 -r f534ace74eea thermferm/thermferm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermferm/thermferm.c Sun May 18 21:24:55 2014 +0200 @@ -0,0 +1,354 @@ +/***************************************************************************** + * 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 "../lib/mbselib.h" +#include "thermferm.h" +#include "mosquitto.h" +#include "sensors.h" + +#ifdef HAVE_WIRINGPI_H + + +int tempA = 80; +int tempB = 80; +int coolerA = 0; +int coolerB = 0; + +bool my_shutdown = false; +static pid_t pgrp, mypid; + +extern bool debug; +extern sys_config Config; +extern int lcdHandle; +extern unsigned char lcdbuf[MAX_LCDS][20][4]; +int lcdupdate; + + +int server(void); +void help(void); +void die(int); + + +void help(void) +{ + fprintf(stdout, "mbsePi-apps thermferm v%s starting\n\n", VERSION); + fprintf(stdout, "Usage: thermferm [-d] [-h]\n"); + fprintf(stdout, " -d --debug Debug and run in foreground\n"); + fprintf(stdout, " -h --help Display this help\n"); +} + + + +void die(int onsig) +{ + switch (onsig) { + case SIGHUP: syslog(LOG_NOTICE, "Got SIGHUP, shutting down"); + break; + case SIGINT: syslog(LOG_NOTICE, "Keyboard interrupt, shutting down"); + break; + case SIGTERM: syslog(LOG_NOTICE, "Got SIGTERM, shutting down"); + break; + default: syslog(LOG_NOTICE, "die() on signal %d", onsig); + } + + my_shutdown = true; +} + + + +void stopLCD(void) +{ + mb_lcdClear(lcdHandle); + setBacklight(0); +} + + + +void stopRCswitch(void) +{ + rc_switch *tmp, *old; + char *cmd = NULL; + int rc; + + for (tmp = Config.rcswitch; tmp; tmp = old) { + old = tmp->next; + cmd = xstrcpy(tmp->address); + cmd = xstrcat(cmd, (char *)",0"); + rc = toggleSwitch(cmd); + if (debug) + fprintf(stdout, "Switch %s rc=%d\n", cmd, rc); + syslog(LOG_NOTICE, "Switch %s rc=%d", cmd, rc); + free(cmd); + cmd = NULL; + } +} + + + +int main(int argc, char *argv[]) +{ + int rc, c, i; + pid_t frk; + char buf[80]; + + while (1) { + int option_index = 0; + static struct option long_options[] = { + {"debug", 0, 0, 'c'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "dh", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'd': debug = true; + break; + case 'h': help(); + return 1; + } + } + + openlog("thermferm", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER); + syslog(LOG_NOTICE, "mbsePi-apps thermferm v%s starting", VERSION); + if (debug) + fprintf(stdout, "mbsePi-apps thermferm v%s starting\n", VERSION); + + if (rdconfig((char *)"thermferm.conf")) { + fprintf(stderr, "Error reading configuration\n"); + syslog(LOG_NOTICE, "halted"); + return 1; + } + + /* + * Catch all the signals we can, and ignore the rest. Note that SIGKILL can't be ignored + * but that's live. This daemon should only be stopped by SIGTERM. + * Don't catch SIGCHLD. + */ + for (i = 0; i < NSIG; i++) { + if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP)) + signal(i, (void (*))die); + } + + if (wiringPiSetup () ) + return 1; + + if ((rc = initLCD (16, 2))) { + fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc); + return 1; + } + + lcdPosition(lcdHandle, 0, 0); + sprintf(buf, " Thermferm"); + mb_lcdPuts(lcdHandle, buf); + lcdPosition(lcdHandle, 0, 1); + sprintf(buf, " Version %s", VERSION); + mb_lcdPuts(lcdHandle, buf); + + if (Config.tx433 != -1) { + if (debug) + fprintf(stdout, "Using 433 MHz transmitter on pin %d\n", Config.tx433); + syslog(LOG_NOTICE, "Using 433 MHz transmitter on pin %d", Config.tx433); + enableTransmit(Config.tx433); + } + + if (debug) { + /* + * For debugging run in foreground. + */ + rc = server(); + } else { + /* + * Server initialization is complete. Now we can fork the + * daemon and return to the user. We need to do a setpgrp + * so that the daemon will no longer be assosiated with the + * users control terminal. This is done before the fork, so + * that the child will not be a process group leader. Otherwise, + * if the child were to open a terminal, it would become + * associated with that terminal as its control terminal. + */ + if ((pgrp = setpgid(0, 0)) == -1) { + syslog(LOG_NOTICE, "setpgpid failed"); + } + + frk = fork(); + switch (frk) { + case -1: + syslog(LOG_NOTICE, "Daemon fork failed: %s", strerror(errno)); + syslog(LOG_NOTICE, "Finished, rc=1"); + stopLCD(); + exit(1); + case 0: /* + * Run the daemon + */ + fclose(stdin); + if (open("/dev/null", O_RDONLY) != 0) { + syslog(LOG_NOTICE, "Reopen of stdin to /dev/null failed"); + _exit(2); + } + fclose(stdout); + if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) { + syslog(LOG_NOTICE, "Reopen of stdout to /dev/null failed"); + _exit(2); + } + fclose(stderr); + if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) { + syslog(LOG_NOTICE, "Reopen of stderr to /dev/null failed"); + _exit(2); + } + mypid = getpid(); + rc = server(); + break; + /* Not reached */ + default: + /* + * Here we detach this process and let the child + * run the deamon process. + */ + syslog(LOG_NOTICE, "Starting daemon with pid %d", frk); + exit(0); + } + } + + syslog(LOG_NOTICE, "Finished, rc=%d", rc); + return rc; +} + + + +int server(void) +{ + char buf[1024]; + w1_therm *tmp1, *old1; + rc_switch *tmp2, *old2; + int rc, run = 0, temp; + + + if (lockprog((char *)"thermferm")) { + syslog(LOG_NOTICE, "Can't lock"); + return 1; + } + + my_mosquitto_init(); + + rc = piThreadCreate(my_sensors_loop); + if (rc) { + fprintf(stderr, "my_sensors_loop thread didn't start rc=%d\n", rc); + syslog(LOG_NOTICE, "my_sensors_loop thread didn't start rc=%d", rc); + } + + snprintf(buf, 1023, "tempA,coolerA,tempB,coolerB"); + logger((char *)"thermferm.log", (char *)"thermferm", buf); + + do { + lcdupdate = FALSE; + + run = my_mosquitto_loop(); + + tmp1 = Config.w1therms; + tmp2 = Config.rcswitch; + if (((tmp1->lastval / 100) < (tempA - 5)) && (coolerA == 1)) { + my_mosquitto_switch(tmp2->address, 0); + coolerA = 0; + syslog(LOG_NOTICE, "Temperature A is %.1f, switched cooler off", (tmp1->lastval / 1000.0)); + lcdupdate = TRUE; + } + if (((tmp1->lastval / 100) > (tempA + 5)) && (coolerA == 0)) { + my_mosquitto_switch(tmp2->address, 1); + coolerA = 1; + syslog(LOG_NOTICE, "Temperature A is %.1f, switched cooler on", (tmp1->lastval / 1000.0)); + lcdupdate = TRUE; + } + old1 = tmp1->next; + tmp1 = old1; + old2 = tmp2->next; + tmp2 = old2; + if (((tmp1->lastval / 100) < (tempB - 5)) && (coolerB == 1)) { + my_mosquitto_switch(tmp2->address, 0); + coolerB = 0; + syslog(LOG_NOTICE, "Temperature B is %.1f, switched cooler off", (tmp1->lastval / 1000.0)); + lcdupdate = TRUE; + } + if (((tmp1->lastval / 100) > (tempB + 5)) && (coolerB == 0)) { + my_mosquitto_switch(tmp2->address, 1); + coolerB = 1; + syslog(LOG_NOTICE, "Temperature B is %.1f, switched cooler on", (tmp1->lastval / 1000.0)); + lcdupdate = TRUE; + } + + if (run && lcdupdate) { + lcdPosition(lcdHandle, 0, 0); + tmp1 = Config.w1therms; + snprintf(buf, 16, "%4.1f %cC %c %s ", tmp1->lastval / 1000.0, 0xdf, coolerA ? '+' : ' ', tmp1->alias); + mb_lcdPuts(lcdHandle, buf); + temp = tmp1->lastval; + old1 = tmp1->next; + tmp1 = old1; + lcdPosition(lcdHandle, 0, 1); + snprintf(buf, 16, "%4.1f %cC %c %s ", tmp1->lastval / 1000.0, 0xdf, coolerB ? '+' : ' ', tmp1->alias); + mb_lcdPuts(lcdHandle, buf); + snprintf(buf, 1023, "%.1f,%s,%.1f,%s", temp / 1000.0, coolerA ? (char *)"on" : (char *)"off", + tmp1->lastval / 1000.0, coolerB ? (char *)"on" : (char *)"off"); + logger((char *)"thermferm.log", (char *)"thermferm", buf); + } + usleep(100000); + + } while (run); + + if (debug) + fprintf(stdout, (char *)"Out of loop\n"); + + /* + * Give threads time to cleanup + */ + usleep(1500000); + + if (Config.tx433 != -1) { + stopRCswitch(); + } + + my_mosquitto_exit(); + stopLCD(); + disableTransmit(); + + ulockprog((char *)"thermferm"); + + if (debug) + fprintf(stdout, "Goodbye\n"); + + return 0; +} + +#else + + +int main(int argc, char *argv[]) +{ + fprintf(stderr, "Compiled on a system without a wiringPi library.\n"); + fprintf(stderr, "This program is useless and will do nothing.\n"); + return 0; +} + + +#endif