Mon, 18 May 2015 21:19:06 +0200
Version 0.3.3, still not for production. Fixed warnings when the simulator code is compiled. Slowed the simulator air temperature change 60 times. More realistic temperature changes for the heater and cooler elements. Improved logic in the simulator.
/***************************************************************************** * 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 "thermometers.h" static int my_shutdown = FALSE; static pid_t pgrp, mypid; extern int debug; extern sys_config Config; #ifdef HAVE_WIRINGPI_H extern int lcdHandle; #endif int server(void); void help(void); void die(int); void help(void) { fprintf(stdout, "mbsePi-apps thermometers v%s starting\n\n", VERSION); fprintf(stdout, "Usage: thermomeneters [-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; } #ifdef HAVE_WIRINGPI_H void stopLCD(void) { lcdClear(lcdHandle); setBacklight(0); } #endif int main(int argc, char *argv[]) { int rc, c, i; pid_t frk; #ifdef HAVE_WIRINGPI_H char buf[80]; #endif 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("thermometers", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER); syslog(LOG_NOTICE, "mbsePi-apps thermometers v%s starting", VERSION); if (debug) fprintf(stdout, "mbsePi-apps thermometers v%s starting\n", VERSION); if (rdconfig((char *)"thermometers.conf")) { fprintf(stderr, "Error reading configuration\n"); syslog(LOG_NOTICE, "Error reading configuration, 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); } #ifdef HAVE_WIRINGPI_H 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); lcdPuts(lcdHandle, "Thermometers"); lcdPosition(lcdHandle, 0, 1); sprintf(buf, "Version %s", VERSION); lcdPuts(lcdHandle, buf); #endif 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"); #ifdef HAVE_WIRINGPI_H stopLCD(); #endif 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) { int temp, rc = 0; #ifdef HAVE_WIRINGPI_H char buf[1024]; int lcdupdate; #endif w1_therm *tmp1; char *device, line[60], *p = NULL; FILE *fp; if (debug) fprintf(stdout, (char *)"Enter loop\n"); do { #ifdef HAVE_WIRINGPI_H lcdupdate = FALSE; #endif /* * Here send our 1-wire sensors values */ for (tmp1 = Config.w1therms; tmp1; tmp1 = tmp1->next) { /* * Build path and alias topic */ device = xstrcpy((char *)"/sys/bus/w1/devices/"); device = xstrcat(device, tmp1->master); device = xstrcat(device, (char *)"/"); device = xstrcat(device, tmp1->name); 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", &temp); if ((rc == 1) && (tmp1->lastval != temp)) { tmp1->lastval = temp; #ifdef HAVE_WIRINGPI_H lcdupdate = TRUE; #endif } } else { syslog(LOG_NOTICE, "sensor %s/%s CRC error", tmp1->master, tmp1->name); } fclose(fp); tmp1->present = 1; } else { tmp1->present = 0; if (debug) printf("sensor %s is missing\n", tmp1->name); } free(device); device = NULL; } #ifdef HAVE_WIRINGPI_H if (lcdupdate) { lcdPosition(lcdHandle, 0, 0); tmp1 = Config.w1therms; snprintf(buf, 16, "%5.1f %cC %s ", tmp1->lastval / 1000.0, 0xdf, tmp1->alias); lcdPuts(lcdHandle, buf); tmp1 = tmp1->next; lcdPosition(lcdHandle, 0, 1); snprintf(buf, 16, "%5.1f %cC %s ", tmp1->lastval / 1000.0, 0xdf, tmp1->alias); lcdPuts(lcdHandle, buf); } #endif if (my_shutdown) { #ifdef HAVE_WIRINGPI_H lcdClear(lcdHandle); lcdPosition(lcdHandle, 0, 0); lcdPuts(lcdHandle, "Shuting down ..."); #endif } usleep(100000); } while (! my_shutdown); if (debug) fprintf(stdout, (char *)"Out of loop\n"); #ifdef HAVE_WIRINGPI_H stopLCD(); #endif return rc; }