# HG changeset patch # User Michiel Broek # Date 1399325611 -7200 # Node ID 9322c619c5258ac526c69c1e360f640575169d74 # Parent 5e0695f6add58423c1de556c0d4d7b08cba48562 Added coolers program, first draft diff -r 5e0695f6add5 -r 9322c619c525 .hgignore --- a/.hgignore Mon May 05 20:25:20 2014 +0200 +++ b/.hgignore Mon May 05 23:33:31 2014 +0200 @@ -9,6 +9,7 @@ rc433/recv rc433/send rc433/sniffer +coolers/coolers syntax: glob *.o diff -r 5e0695f6add5 -r 9322c619c525 configure --- a/configure Mon May 05 20:25:20 2014 +0200 +++ b/configure Mon May 05 23:33:31 2014 +0200 @@ -2028,11 +2028,11 @@ ac_config_headers="$ac_config_headers config.h" -SUBDIRS="lib rc433 thermometers" +SUBDIRS="lib coolers rc433 thermometers" PACKAGE="mbsePi-apps" -VERSION="0.0.3" +VERSION="0.0.4" COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved" CYEARS="2014" diff -r 5e0695f6add5 -r 9322c619c525 configure.ac --- a/configure.ac Mon May 05 20:25:20 2014 +0200 +++ b/configure.ac Mon May 05 23:33:31 2014 +0200 @@ -2,13 +2,13 @@ AC_INIT(thermometers/main.c) AM_CONFIG_HEADER(config.h) -SUBDIRS="lib rc433 thermometers" +SUBDIRS="lib coolers rc433 thermometers" AC_SUBST(SUBDIRS) dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="mbsePi-apps" -VERSION="0.0.3" +VERSION="0.0.4" COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved" CYEARS="2014" AC_SUBST(PACKAGE) diff -r 5e0695f6add5 -r 9322c619c525 coolers/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/Makefile Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,60 @@ +# Makefile for the mbsePi-apps/coolers. + +include ../Makefile.global + +SRCS = coolers.c mosquitto.c sensors.c +HDRS = coolers.h mosquitto.h sensors.h +OBJS = coolers.o mosquitto.o sensors.o +SLIBS = ../lib/libmbse.a +TARGET = coolers +OTHER = Makefile + +############################################################################# + +.c.o: + ${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $< + +all: ${TARGET} + +coolers: ${OBJS} ${SLIBS} + ${CC} -o coolers ${OBJS} ${LDFLAGS} ${LIBS} ${SLIBS} + +clean: + rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak + +install: all + ${INSTALL} -c -s -g root -o root -m 0755 thermometers ${BINDIR} + +filelist: Makefile + BASE=`pwd`; \ + BASE=`basename $${BASE}`; \ + (for f in ${SRCS} ${HDRS} ${OTHER} ;do echo ${PACKAGE}-${VERSION}/$${BASE}/$$f; done) >filelist + +depend: + @rm -f Makefile.bak; \ + mv Makefile Makefile.bak; \ + sed -e '/^# DO NOT DELETE/,$$d' Makefile.bak >Makefile; \ + ${ECHO} '# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT' \ + >>Makefile; \ + ${ECHO} '# Dependencies generated by make depend' >>Makefile; \ + for f in ${SRCS}; \ + do \ + ${ECHO} "Dependencies for $$f:\c"; \ + ${ECHO} "`basename $$f .c`.o:\c" >>Makefile; \ + for h in `sed -n -e \ + 's/^#[ ]*include[ ]*"\([^"]*\)".*/\1/p' $$f`; \ + do \ + ${ECHO} " $$h\c"; \ + ${ECHO} " $$h\c" >>Makefile; \ + done; \ + ${ECHO} " done."; \ + ${ECHO} "" >>Makefile; \ + done; \ + ${ECHO} '# End of generated dependencies' >>Makefile + +# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT +# Dependencies generated by make depend +coolers.o: ../lib/mbselib.h coolers.h mosquitto.h sensors.h +mosquitto.o: ../lib/mbselib.h mosquitto.h +sensors.o: ../lib/mbselib.h sensors.h +# End of generated dependencies diff -r 5e0695f6add5 -r 9322c619c525 coolers/coolers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/coolers.c Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,249 @@ +/***************************************************************************** + * 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 "coolers.h" +#include "mosquitto.h" +#include "sensors.h" + +#ifdef HAVE_WIRINGPI_H + + +bool shutdown = false; +static pid_t pgrp, mypid; + +extern bool debug; +extern sys_config Config; +extern int lcdHandle; +int lcdupdate; + +int server(void); +void help(void); +void die(int); + + +void help(void) +{ + fprintf(stdout, "mbsePi-apps coolers v%s starting\n\n", VERSION); + fprintf(stdout, "Usage: coolers [-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); + } + + shutdown = true; +} + + + +void stopLCD(void) +{ + lcdClear(lcdHandle); + setBacklight(0); +} + + + +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("coolers", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER); + syslog(LOG_NOTICE, "mbsePi-apps coolers v%s starting", VERSION); + if (debug) + fprintf(stdout, "mbsePi-apps coolers v%s starting\n", VERSION); + + if (rdconfig((char *)"coolers.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 ((rc = initLCD (16, 2))) { + fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc); + return 1; + } + + lcdPosition(lcdHandle, 0, 0); + lcdPuts(lcdHandle, "Coolers"); + lcdPosition(lcdHandle, 0, 1); + sprintf(buf, "Version %s", VERSION); + lcdPuts(lcdHandle, buf); + + 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; + int run = 0; + + my_mosquitto_init(); + + do { + lcdupdate = FALSE; + + my_sensors_loop(); + run = my_mosquitto_loop(); + + if (run && lcdupdate) { + lcdPosition(lcdHandle, 0, 0); + tmp1 = Config.w1therms; + snprintf(buf, 16, "%4.1f %cC %c %s ", tmp1->lastval / 1000.0, 0xdf, ' ', tmp1->alias); + lcdPuts(lcdHandle, buf); + old1 = tmp1->next; + tmp1 = old1; + lcdPosition(lcdHandle, 0, 1); + snprintf(buf, 16, "%4.1f %cC %c %s ", tmp1->lastval / 1000.0, 0xdf, ' ', tmp1->alias); + lcdPuts(lcdHandle, buf); + } + + } while (run); + + if (debug) + fprintf(stdout, (char *)"Out of loop\n"); + + my_mosquitto_exit(); + stopLCD(); + + 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 diff -r 5e0695f6add5 -r 9322c619c525 coolers/coolers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/coolers.h Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,9 @@ +#ifndef _MAIN_H +#define _MAIN_H + + +#define TRUE 1 +#define FALSE 0 + + +#endif diff -r 5e0695f6add5 -r 9322c619c525 coolers/mosquitto.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/mosquitto.c Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,324 @@ +/***************************************************************************** + * 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 "coolers.h" + +#ifdef HAVE_WIRINGPI_H + + +#define STATUS_CONNECTING 0 +#define STATUS_CONNACK_RECVD 1 +#define STATUS_WAITING 2 + +/* Global variables for use in callbacks. */ +struct mosquitto *mymosq = NULL; +char *myhostname; +static int qos = 0; +static int status = STATUS_CONNECTING; +static int mid_sent = 0; +static int last_mid = -1; +static int last_mid_sent = -1; +static bool connected = true; +static bool disconnect_sent = false; +static bool connect_lost = false; + +extern bool shutdown; +extern bool debug; +extern sys_config Config; +extern int lcdHandle; +extern int lcdupdate; + + +void my_connect_callback(struct mosquitto *mosq, void *obj, int result) +{ + if (connect_lost) { + connect_lost = false; + syslog(LOG_NOTICE, "Reconnect: %s", mosquitto_connack_string(result)); + } + + if (!result) { + status = STATUS_CONNACK_RECVD; + } else { + syslog(LOG_NOTICE, "my_connect_callback: %s\n", mosquitto_connack_string(result)); + } +} + + + +void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc) +{ + if (shutdown) { + syslog(LOG_NOTICE, "Acknowledged DISCONNECT from %s", Config.mosq_host); + connected = false; + } else { + /* + * The remove server was brought down. We must keep running + */ + syslog(LOG_NOTICE, "Received DISCONNECT from %s, connection lost", Config.mosq_host); + connect_lost = true; + } +} + + + +void my_publish_callback(struct mosquitto *mosq, void *obj, int mid) +{ + last_mid_sent = mid; +} + + + +void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str) +{ + syslog(LOG_NOTICE, "MQTT: %s", str); + printf("MQTT: %s\n", str); +} + + + +int my_mosquitto_init(void) +{ + char *id = NULL, *state = NULL; + char buf[1024]; + int rc, keepalive = 60; + unsigned int max_inflight = 20; + char err[1024]; + w1_therm *tmp1, *old1; + rc_switch *tmp2, *old2; + char *alias; + + /* + * Initialize mosquitto communication + */ + mosquitto_lib_init(); + + gethostname(buf, 255); + myhostname = xstrcpy(buf); + + /* + * Build MQTT id + */ + id = xstrcpy((char *)"coolers/"); + id = xstrcat(id, myhostname); + if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH) { + /* + * Enforce maximum client id length of 23 characters + */ + id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; + } + + mymosq = mosquitto_new(id, true, NULL); + if(!mymosq) { + switch(errno) { + case ENOMEM: + syslog(LOG_NOTICE, "mosquitto_new: Out of memory"); + break; + case EINVAL: + syslog(LOG_NOTICE, "mosquitto_new: Invalid id"); + break; + } + mosquitto_lib_cleanup(); + return 1; + } + + if (debug) { + mosquitto_log_callback_set(mymosq, my_log_callback); + } + + /* + * Set our will + */ + state = xstrcpy((char *)"clients/"); + state = xstrcat(state, myhostname); + state = xstrcat(state, (char *)"/coolers/state"); + sprintf(buf, "0"); + if ((rc = mosquitto_will_set(mymosq, state, strlen(buf), buf, qos, true))) { + if (rc == MOSQ_ERR_INVAL) { + syslog(LOG_NOTICE, "mosquitto_will_set: input parameters invalid"); + } else if (rc == MOSQ_ERR_NOMEM) { + syslog(LOG_NOTICE, "mosquitto_will_set: Out of Memory"); + } else if (rc == MOSQ_ERR_PAYLOAD_SIZE) { + syslog(LOG_NOTICE, "mosquitto_will_set: invalid payload size"); + } + mosquitto_lib_cleanup(); + return rc; + } + + mosquitto_max_inflight_messages_set(mymosq, max_inflight); + mosquitto_connect_callback_set(mymosq, my_connect_callback); + mosquitto_disconnect_callback_set(mymosq, my_disconnect_callback); + mosquitto_publish_callback_set(mymosq, my_publish_callback); + + if ((rc = mosquitto_connect(mymosq, Config.mosq_host, Config.mosq_port, keepalive))) { + if (rc == MOSQ_ERR_ERRNO) { + strerror_r(errno, err, 1024); + syslog(LOG_NOTICE, "mosquitto_connect: error: %s", err); + } else { + syslog(LOG_NOTICE, "mosquitto_connect: unable to connect (%d)", rc); + } + mosquitto_lib_cleanup(); + return rc; + } + syslog(LOG_NOTICE, "Connected with %s:%d", Config.mosq_host, Config.mosq_port); + + /* + * Initialise is complete, report our presence state + */ + mosquitto_loop_start(mymosq); + sprintf(buf, "1"); + rc = mosquitto_publish(mymosq, &mid_sent, state, strlen(buf), buf, qos, 1); + + /* + * Report alias names + */ + for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) { + old1 = tmp1->next; + + alias = xstrcpy((char *)"/raw/"); + alias = xstrcat(alias, myhostname); + alias = xstrcat(alias, (char *)"/coolers/w1/"); + alias = xstrcat(alias, tmp1->master); + alias = xstrcat(alias, (char *)"/"); + alias = xstrcat(alias, tmp1->name); + alias = xstrcat(alias, (char *)"/alias"); + + sprintf(buf, "%s", tmp1->alias); + if ((rc = mosquitto_publish(mymosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) { + if (rc == MOSQ_ERR_NO_CONN) + mosquitto_reconnect(mymosq); + else + syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc); + } + + free(alias); + alias = NULL; + } + + for (tmp2 = Config.rcswitch; tmp2; tmp2 = old2) { + old2 = tmp2->next; + + alias = xstrcpy((char *)"/raw/"); + alias = xstrcat(alias, myhostname); + alias = xstrcat(alias, (char *)"/coolers/rcswitch/"); + alias = xstrcat(alias, tmp2->address); + alias = xstrcat(alias, (char *)"/alias"); + + sprintf(buf, "%s", tmp2->alias); + if ((rc = mosquitto_publish(mymosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) { + if (rc == MOSQ_ERR_NO_CONN) + mosquitto_reconnect(mymosq); + else + syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc); + } + + free(alias); + alias = NULL; + } + + return 0; +} + + + +int my_mosquitto_loop(void) +{ + w1_therm *tmp1, *old1; + char buf[1024], *alias, *state = NULL; + int rc; + + if (status == STATUS_CONNACK_RECVD) { + /* + * Here send our 1-wire sensors values + */ + for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) { + old1 = tmp1->next; + + /* + * Build path and alias topic + */ + alias = xstrcpy((char *)"/raw/"); + alias = xstrcat(alias, myhostname); + alias = xstrcat(alias, (char *)"/coolers/w1/"); + alias = xstrcat(alias, tmp1->master); + alias = xstrcat(alias, (char *)"/"); + alias = xstrcat(alias, tmp1->name); + alias = xstrcat(alias, (char *)"/temperature"); + + if (tmp1->update) { + /* + * Temperature is changed and valid, update and publish this. + */ + sprintf(buf, "%.1f", tmp1->lastval / 1000.0); + if ((rc = mosquitto_publish(mymosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) { + if (rc == MOSQ_ERR_NO_CONN) + mosquitto_reconnect(mymosq); + else + syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc); + } + tmp1->update = FALSE; + } + + free(alias); + alias = NULL; + } + + if (shutdown) { + /* + * Final publish 0 to clients//coolers/state + */ + sprintf(buf, "0"); + mosquitto_publish(mymosq, &mid_sent, state, strlen(buf), buf, qos, true); + last_mid = mid_sent; + status = STATUS_WAITING; + lcdClear(lcdHandle); + lcdPosition(lcdHandle, 0, 0); + lcdPuts(lcdHandle, "Shuting down ..."); + } + + usleep(100000); + + } else if (status == STATUS_WAITING) { + if (debug) + fprintf(stdout, (char *)"Waiting\n"); + if (last_mid_sent == last_mid && disconnect_sent == false) { + mosquitto_disconnect(mymosq); + disconnect_sent = true; + } + usleep(100000); + } + rc = MOSQ_ERR_SUCCESS; + + return (rc == MOSQ_ERR_SUCCESS && connected); +} + + + +void my_mosquitto_exit(void) +{ + mosquitto_loop_stop(mymosq, false); + mosquitto_destroy(mymosq); + mosquitto_lib_cleanup(); +} + + +#endif diff -r 5e0695f6add5 -r 9322c619c525 coolers/mosquitto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/mosquitto.h Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,8 @@ +#ifndef MY_MOSQUITTO_H +#define MY_MOSQUITTO_H + +void my_mosquitto_init(void); +int my_mosquitto_loop(void); +void my_mosquitto_exit(void); + +#endif diff -r 5e0695f6add5 -r 9322c619c525 coolers/sensors.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/sensors.c Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,122 @@ +/***************************************************************************** + * 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 "sensors.h" + +#ifdef HAVE_WIRINGPI_H + + +extern char *myhostname; +extern bool debug; +extern sys_config Config; +extern int lcdHandle; +extern int lcdupdate; + + + +void my_sensors_loop(void) +{ + w1_therm *tmp1, *old1; + char *device, line[60], *p = NULL; + FILE *fp; + int temp, rc, deviation; + + /* + * Here send our 1-wire sensors values + */ + for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) { + old1 = 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)) { + /* + * 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 ((tmp1->lastval == 0) || + (tmp1->lastval && (temp > (tmp1->lastval - deviation)) && (temp < (tmp1->lastval + deviation)))) { + /* + * Temperature is changed and valid, update and publish this. + */ + tmp1->update = TRUE; + } else { + syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, tmp1->lastval, temp); + if (debug) { + fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, tmp1->lastval, temp); + } + } + tmp1->lastval = temp; + lcdupdate = TRUE; + } + } 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; + } +} + + + +#endif diff -r 5e0695f6add5 -r 9322c619c525 coolers/sensors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coolers/sensors.h Mon May 05 23:33:31 2014 +0200 @@ -0,0 +1,6 @@ +#ifndef MY_SENSORS_H +#define MY_SENSORS_H + +void my_sensors_loop(void); + +#endif diff -r 5e0695f6add5 -r 9322c619c525 lib/mbselib.h --- a/lib/mbselib.h Mon May 05 20:25:20 2014 +0200 +++ b/lib/mbselib.h Mon May 05 23:33:31 2014 +0200 @@ -48,6 +48,7 @@ char *alias; /* Friendly name */ int present; /* 1=present, 0=absent */ int lastval; /* Last valid value */ + int update; /* Value updated */ } w1_therm; typedef struct _rc_switch { diff -r 5e0695f6add5 -r 9322c619c525 lib/rdconfig.c --- a/lib/rdconfig.c Mon May 05 20:25:20 2014 +0200 +++ b/lib/rdconfig.c Mon May 05 23:33:31 2014 +0200 @@ -264,6 +264,7 @@ (*tmpm)->alias = xstrcpy(r); (*tmpm)->present = 0; (*tmpm)->lastval = 0; + (*tmpm)->update = 0; return 0; }