Removed library, bumped to version 0.0.7

Sun, 25 May 2014 22:06:56 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 25 May 2014 22:06:56 +0200
changeset 51
a03b6dac5398
parent 50
8b5e8f1e172d
child 52
4387a6b11eb3

Removed library, bumped to version 0.0.7

.hgignore file | annotate | diff | comparison | revisions
config.h.in file | annotate | diff | comparison | revisions
configure file | annotate | diff | comparison | revisions
configure.ac file | annotate | diff | comparison | revisions
dht11/Makefile file | annotate | diff | comparison | revisions
dht11/dht11.c file | annotate | diff | comparison | revisions
dht11/dht11.h file | annotate | diff | comparison | revisions
lib/Makefile file | annotate | diff | comparison | revisions
lib/dht11.c file | annotate | diff | comparison | revisions
lib/lcd-pcf8574.c file | annotate | diff | comparison | revisions
lib/lock.c file | annotate | diff | comparison | revisions
lib/logger.c file | annotate | diff | comparison | revisions
lib/mbselib.h file | annotate | diff | comparison | revisions
lib/rc-switch.c file | annotate | diff | comparison | revisions
lib/rdconfig.c file | annotate | diff | comparison | revisions
lib/xutil.c file | annotate | diff | comparison | revisions
rc433/Makefile file | annotate | diff | comparison | revisions
rc433/rc-switch.c file | annotate | diff | comparison | revisions
rc433/rc433.h file | annotate | diff | comparison | revisions
rc433/recv.c file | annotate | diff | comparison | revisions
rc433/recv.h file | annotate | diff | comparison | revisions
rc433/xutil.c file | annotate | diff | comparison | revisions
thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/lcd-pcf8574.c file | annotate | diff | comparison | revisions
thermferm/lock.c file | annotate | diff | comparison | revisions
thermferm/logger.c file | annotate | diff | comparison | revisions
thermferm/rc-switch.c file | annotate | diff | comparison | revisions
thermferm/rdconfig.c file | annotate | diff | comparison | revisions
thermferm/sensors.c file | annotate | diff | comparison | revisions
thermferm/sensors.h file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/server.h file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
thermferm/xutil.c file | annotate | diff | comparison | revisions
thermometers/Makefile file | annotate | diff | comparison | revisions
thermometers/lcd-pcf8574.c file | annotate | diff | comparison | revisions
thermometers/main.c file | annotate | diff | comparison | revisions
thermometers/main.h file | annotate | diff | comparison | revisions
thermometers/rdconfig.c file | annotate | diff | comparison | revisions
thermometers/thermometers.c file | annotate | diff | comparison | revisions
thermometers/thermometers.h file | annotate | diff | comparison | revisions
thermometers/xutil.c file | annotate | diff | comparison | revisions
--- a/.hgignore	Sun May 25 16:39:54 2014 +0200
+++ b/.hgignore	Sun May 25 22:06:56 2014 +0200
@@ -15,4 +15,4 @@
 syntax: glob
 *.o
 */filelist
-lib/*.a
+www/*
--- a/config.h.in	Sun May 25 16:39:54 2014 +0200
+++ b/config.h.in	Sun May 25 22:06:56 2014 +0200
@@ -12,3 +12,5 @@
 /* Define if you have the <wiringPi.h> header file. */
 #undef HAVE_WIRINGPI_H
 
+/* Define if you have the <mosquitto.h> header file. */
+#undef HAVE_MOSQUITTO_H
--- a/configure	Sun May 25 16:39:54 2014 +0200
+++ b/configure	Sun May 25 22:06:56 2014 +0200
@@ -582,7 +582,7 @@
 PACKAGE_BUGREPORT=
 PACKAGE_URL=
 
-ac_unique_file="thermometers/main.c"
+ac_unique_file="thermometers/thermometers.c"
 ac_default_prefix=/usr/local
 # Factoring default headers for most tests.
 ac_includes_default="\
@@ -2028,11 +2028,11 @@
 
 ac_config_headers="$ac_config_headers config.h"
 
-SUBDIRS="lib dht11 rc433 thermferm thermometers"
+SUBDIRS="dht11 rc433 thermferm thermometers"
 
 
 PACKAGE="mbsePi-apps"
-VERSION="0.0.6"
+VERSION="0.0.7"
 COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved"
 CYEARS="2014"
 
@@ -3091,57 +3091,6 @@
 fi
 
 if test "$result" = "yes"; then
-  LIBS="$LIBS -lmosquitto"
-else
-  as_fn_error $? "libmosquitto not found" "$LINENO" 5
-fi
-
-
-WIRINGPI=No
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wiringPiSetup in -lwiringPi" >&5
-$as_echo_n "checking for wiringPiSetup in -lwiringPi... " >&6; }
-if ${ac_cv_lib_wiringPi_wiringPiSetup+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lwiringPi  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char wiringPiSetup ();
-int
-main ()
-{
-return wiringPiSetup ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_wiringPi_wiringPiSetup=yes
-else
-  ac_cv_lib_wiringPi_wiringPiSetup=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wiringPi_wiringPiSetup" >&5
-$as_echo "$ac_cv_lib_wiringPi_wiringPiSetup" >&6; }
-if test "x$ac_cv_lib_wiringPi_wiringPiSetup" = xyes; then :
-  result=yes
-else
-  result=no
-fi
-
-if test "$result" = "yes"; then
-  LIBS="$LIBS -lwiringPi -lwiringPiDev"
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3539,7 +3488,71 @@
 done
 
 
-for ac_header in wiringPi.h
+for ac_header in mosquitto.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "mosquitto.h" "ac_cv_header_mosquitto_h" "$ac_includes_default"
+if test "x$ac_cv_header_mosquitto_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MOSQUITTO_H 1
+_ACEOF
+ MOSQUITTO=Yes
+else
+  MOSQUITTO=No
+fi
+
+done
+
+else
+  as_fn_error $? "libmosquitto not found" "$LINENO" 5
+fi
+
+
+WIRINGPI=No
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wiringPiSetup in -lwiringPi" >&5
+$as_echo_n "checking for wiringPiSetup in -lwiringPi... " >&6; }
+if ${ac_cv_lib_wiringPi_wiringPiSetup+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lwiringPi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char wiringPiSetup ();
+int
+main ()
+{
+return wiringPiSetup ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_wiringPi_wiringPiSetup=yes
+else
+  ac_cv_lib_wiringPi_wiringPiSetup=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wiringPi_wiringPiSetup" >&5
+$as_echo "$ac_cv_lib_wiringPi_wiringPiSetup" >&6; }
+if test "x$ac_cv_lib_wiringPi_wiringPiSetup" = xyes; then :
+  result=yes
+else
+  result=no
+fi
+
+if test "$result" = "yes"; then
+  LIBS="$LIBS -lwiringPi -lwiringPiDev"
+  for ac_header in wiringPi.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "wiringPi.h" "ac_cv_header_wiringPi_h" "$ac_includes_default"
 if test "x$ac_cv_header_wiringPi_h" = xyes; then :
--- a/configure.ac	Sun May 25 16:39:54 2014 +0200
+++ b/configure.ac	Sun May 25 22:06:56 2014 +0200
@@ -1,14 +1,14 @@
 dnl Process this file with autoconf to produce a configure script.
 
-AC_INIT(thermometers/main.c)
+AC_INIT(thermometers/thermometers.c)
 AM_CONFIG_HEADER(config.h)
-SUBDIRS="lib dht11 rc433 thermferm thermometers"
+SUBDIRS="dht11 rc433 thermferm thermometers"
 AC_SUBST(SUBDIRS)
 
 dnl General settings
 dnl After changeing the version number, run autoconf!
 PACKAGE="mbsePi-apps"
-VERSION="0.0.6"
+VERSION="0.0.7"
 COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved"
 CYEARS="2014"
 AC_SUBST(PACKAGE)
@@ -34,7 +34,7 @@
 #
 AC_CHECK_LIB(mosquitto,mosquitto_lib_init,result=yes,result=no)
 if test "$result" = "yes"; then
-  LIBS="$LIBS -lmosquitto"
+  AC_CHECK_HEADERS(mosquitto.h,MOSQUITTO=Yes,MOSQUITTO=No)
 else
   AC_MSG_ERROR(libmosquitto not found)
 fi
--- a/dht11/Makefile	Sun May 25 16:39:54 2014 +0200
+++ b/dht11/Makefile	Sun May 25 22:06:56 2014 +0200
@@ -5,7 +5,6 @@
 SRCS		= dht11.c
 HDRS		= dht11.h
 OBJS		= dht11.o
-SLIBS		= ../lib/libmbse.a
 TARGET		= dht11
 OTHER		= Makefile
 
@@ -54,5 +53,5 @@
 
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
-dht11.o: ../lib/mbselib.h dht11.h
+dht11.o: dht11.h
 # End of generated dependencies
--- a/dht11/dht11.c	Sun May 25 16:39:54 2014 +0200
+++ b/dht11/dht11.c	Sun May 25 22:06:56 2014 +0200
@@ -20,14 +20,148 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
-#include "../lib/mbselib.h"
 #include "dht11.h"
 
 #ifdef HAVE_WIRINGPI_H
 
-extern int	dht11_valid;
-extern int	dht11_temperature;
-extern int	dht11_humidity;
+#define MAXTIMINGS 100
+
+int		dht11_pin = -1;
+int		dht11_temperature = -1;
+int		dht11_humidity = -1;
+int		dht11_valid = false;
+int		dht11_t_offset = 0;
+int		dht11_h_offset = 0;
+
+
+
+static uint8_t sizecvt(const int read_value) {
+    /* 
+     * digitalRead() and friends from wiringpi are defined as returning a value
+     *            < 256. However, they are returned as int() types. This is a safety function 
+     */
+    if (read_value > 255 || read_value < 0) {
+	syslog(LOG_NOTICE, "invalid data from wiringPi library");
+    }
+		  
+    return (uint8_t)read_value;
+}
+
+
+
+/*
+ * DHT11 sensor read. This should be used in a thread loop.
+ */
+void dht11Read(void) {
+    int         	tries = 5;
+    unsigned short	got_correct_data = 0;
+
+    if (dht11_pin == -1)
+	return;
+
+    while (tries && !got_correct_data) {
+	uint8_t	laststate = HIGH;
+	uint8_t	counter = 0;
+	uint8_t	j = 0, i = 0;
+	int	dht11_dat[5] = {0,0,0,0,0};
+
+	/*
+	 * Select output mode to send the start signal.
+	 */
+	pinMode(dht11_pin, OUTPUT);                 
+	digitalWrite(dht11_pin, HIGH);
+	usleep(1000);
+
+	/*
+	 * Low for at least 18 milliseconds
+	 */
+	digitalWrite(dht11_pin, LOW);
+	usleep(20000);
+	digitalWrite(dht11_pin, HIGH);
+	pinMode(dht11_pin, INPUT);
+
+	/*
+	 * Detect change and read data
+	 */
+	for (i=0; i<MAXTIMINGS; i++) {
+	    counter = 0;
+	    delayMicroseconds(10);
+	    while (sizecvt(digitalRead(dht11_pin)) == laststate) {
+		counter++;
+		delayMicroseconds(1);
+		if (counter == 255) {
+		    break;
+		}
+	    }
+	    laststate = sizecvt(digitalRead(dht11_pin));
+
+	    if (counter == 255) 
+		break;
+
+	    /*
+	     * ignore first 3 transitions
+	     */
+	    if ((i >= 4) && (i%2 == 0)) {
+
+		// shove each bit into the storage bytes
+		dht11_dat[(int)((double)j/8)] <<= 1;
+		if (counter > 16)
+		    dht11_dat[(int)((double)j/8)] |= 1;
+		j++;
+	    }
+	}
+
+	/*
+	 * If there is no sensor, j = 0
+	 */
+	if ((counter == 255) && (j == 0)) {
+	    if (dht11_temperature != -1) {
+		syslog(LOG_NOTICE, "dht11 sensor disappeared");
+	    } else {
+		syslog(LOG_NOTICE, "dht11 sensor not present");
+	    }
+	    dht11_temperature = -1;
+	    dht11_humidity = -1;
+	    dht11_valid = false;
+	    return;
+	} 
+
+	/*
+	 * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
+	 * print it out if data is good
+	 */
+	if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF))) {
+		got_correct_data = 1;
+
+		int h = dht11_dat[0] + dht11_dat[1];
+		int t = (dht11_dat[2] & 0x7F) + dht11_dat[3];
+		t += dht11_t_offset;
+		h += dht11_h_offset;
+
+		if ((dht11_dat[2] & 0x80) != 0) 
+		    t *= -1;
+
+		dht11_temperature = t;
+		dht11_humidity = h;
+		dht11_valid = true;
+	} else {
+		tries--;
+		if (tries == 0)
+		    syslog(LOG_INFO, "dht11 data checksum was wrong 5 times");
+		usleep(100000);
+	}
+    }
+}
+
+
+
+void dht11Init(int pin, int t_offset, int h_offset) {
+    dht11_pin = pin;
+    dht11_t_offset = t_offset;
+    dht11_h_offset = h_offset;
+}
+
+
 
 int main(int argc, char *argv[]) {
   
--- a/dht11/dht11.h	Sun May 25 16:39:54 2014 +0200
+++ b/dht11/dht11.h	Sun May 25 22:06:56 2014 +0200
@@ -5,5 +5,7 @@
 #define TRUE 1
 #define FALSE 0
 
+#include <stdio.h>
+
 
 #endif
--- a/lib/Makefile	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-# Makefile for the library files.
-
-include ../Makefile.global
-
-SRCS		= $(wildcard *.c)
-OBJS		= $(SRCS:.c=.o)
-HDRS		= mbselib.h
-TARGET		= libmbse.a
-
-#############################################################################
-
-.c.o:
-		${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $<
-
-all:		${TARGET}
-
-libmbse.a:	${OBJS}
-		ar r $@ $?
-		${RANLIB} $@
-
-clean:
-		rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak
-
-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
-rc-switch.o: ../config.h mbselib.h
-lock.o: ../config.h mbselib.h
-logger.o: ../config.h mbselib.h
-lcd-pcf8574.o: ../config.h mbselib.h
-xutil.o: ../config.h mbselib.h
-dht11.o: ../config.h mbselib.h
-rdconfig.o: ../config.h mbselib.h
-# End of generated dependencies
--- a/lib/dht11.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2014
- *   
- * Michiel Broek <mbroek at mbse dot eu>
- *
- * This file is part of the mbsePi-apps
- *
- * Parts original by CurlyMo from the pilight project.
- *
- * 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 "../config.h"
-#include "mbselib.h"
-
-#ifdef HAVE_WIRINGPI_H
-
-#define MAXTIMINGS 100
-
-int		dht11_pin = -1;
-int		dht11_temperature = -1;
-int		dht11_humidity = -1;
-int		dht11_valid = false;
-int		dht11_t_offset = 0;
-int		dht11_h_offset = 0;
-
-
-
-static uint8_t sizecvt(const int read_value) {
-    /* 
-     * digitalRead() and friends from wiringpi are defined as returning a value
-     *            < 256. However, they are returned as int() types. This is a safety function 
-     */
-    if (read_value > 255 || read_value < 0) {
-	syslog(LOG_NOTICE, "invalid data from wiringPi library");
-    }
-		  
-    return (uint8_t)read_value;
-}
-
-
-
-/*
- * DHT11 sensor read. This should be used in a thread loop.
- */
-void dht11Read(void) {
-    int         	tries = 5;
-    unsigned short	got_correct_data = 0;
-
-    if (dht11_pin == -1)
-	return;
-
-    while (tries && !got_correct_data) {
-	uint8_t	laststate = HIGH;
-	uint8_t	counter = 0;
-	uint8_t	j = 0, i = 0;
-	int	dht11_dat[5] = {0,0,0,0,0};
-
-	/*
-	 * Select output mode to send the start signal.
-	 */
-	pinMode(dht11_pin, OUTPUT);                 
-	digitalWrite(dht11_pin, HIGH);
-	usleep(1000);
-
-	/*
-	 * Low for at least 18 milliseconds
-	 */
-	digitalWrite(dht11_pin, LOW);
-	usleep(20000);
-	digitalWrite(dht11_pin, HIGH);
-	pinMode(dht11_pin, INPUT);
-
-	/*
-	 * Detect change and read data
-	 */
-	for (i=0; i<MAXTIMINGS; i++) {
-	    counter = 0;
-	    delayMicroseconds(10);
-	    while (sizecvt(digitalRead(dht11_pin)) == laststate) {
-		counter++;
-		delayMicroseconds(1);
-		if (counter == 255) {
-		    break;
-		}
-	    }
-	    laststate = sizecvt(digitalRead(dht11_pin));
-
-	    if (counter == 255) 
-		break;
-
-	    /*
-	     * ignore first 3 transitions
-	     */
-	    if ((i >= 4) && (i%2 == 0)) {
-
-		// shove each bit into the storage bytes
-		dht11_dat[(int)((double)j/8)] <<= 1;
-		if (counter > 16)
-		    dht11_dat[(int)((double)j/8)] |= 1;
-		j++;
-	    }
-	}
-
-	/*
-	 * If there is no sensor, j = 0
-	 */
-	if ((counter == 255) && (j == 0)) {
-	    if (dht11_temperature != -1) {
-		syslog(LOG_NOTICE, "dht11 sensor disappeared");
-	    } else {
-		syslog(LOG_NOTICE, "dht11 sensor not present");
-	    }
-	    dht11_temperature = -1;
-	    dht11_humidity = -1;
-	    dht11_valid = false;
-	    return;
-	} 
-
-	/*
-	 * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
-	 * print it out if data is good
-	 */
-	if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF))) {
-		got_correct_data = 1;
-
-		int h = dht11_dat[0] + dht11_dat[1];
-		int t = (dht11_dat[2] & 0x7F) + dht11_dat[3];
-		t += dht11_t_offset;
-		h += dht11_h_offset;
-
-		if ((dht11_dat[2] & 0x80) != 0) 
-		    t *= -1;
-
-		dht11_temperature = t;
-		dht11_humidity = h;
-		dht11_valid = true;
-	} else {
-		tries--;
-		if (tries == 0)
-		    syslog(LOG_INFO, "dht11 data checksum was wrong 5 times");
-		usleep(100000);
-	}
-    }
-}
-
-
-
-void dht11Init(int pin, int t_offset, int h_offset) {
-    dht11_pin = pin;
-    dht11_t_offset = t_offset;
-    dht11_h_offset = h_offset;
-}
-
-
-#endif
-
--- a/lib/lcd-pcf8574.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * lcd-pcf8574.c:
- *	Text-based LCD driver library code
- *	This is designed to drive the HD44780U LCD display connected via
- *	a "LCM1602 IIC  A0 A1 A2" board with a PCF8574 I2C controller.
- *
- * Copyright (c) 2012-2013 Gordon Henderson.
- * Copyright (c) 2014 Michiel Broek.
- ***********************************************************************
- *
- *    mbsePi is free software: you can redistribute it and/or modify
- *    it under the terms of the GNU Lesser General Public License as published by
- *    the Free Software Foundation, either version 3 of the License, or
- *    (at your option) any later version.
- *
- *    mbsePi 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 Lesser General Public License for more details.
- *
- *    You should have received a copy of the GNU Lesser General Public License
- *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
- ***********************************************************************
- */
-
-#include "../config.h"
-#include "mbselib.h"
-
-#ifdef HAVE_WIRINGPI_H
-
-int			lcdHandle;
-unsigned char		lcdbuf[MAX_LCDS][20][4];
-
-struct lcdDataStruct
-{
-    int bits, rows, cols ;
-    int rsPin, strbPin ;
-    int dataPins [8] ;
-    int cx, cy ;
-};
-extern struct lcdDataStruct	*lcds [MAX_LCDS];
-
-
-/*
- * Some LCD functions are extended shadow copies of the wiringPi functions.
- * The difference is that the lcdbuf will be updated with the contents on
- * the hardware display. This copy can then be used for a remote display
- */
-
-
-/*
- * setBacklight:
- *********************************************************************************
- */
-
-void setBacklight (int value)
-{
-  pinMode (AF_BACKLIGHT, OUTPUT) ;
-  digitalWrite (AF_BACKLIGHT, (value & 1)) ;
-}
-
-
-
-/*
- * initLCD:
- *********************************************************************************
- */
-
-int initLCD (int cols, int rows)
-{
-    int	x, y;
-
-    if (!((rows == 1) || (rows == 2) || (rows == 4))) {
-    	fprintf (stderr, "rows must be 1, 2 or 4\n") ;
-    	return EXIT_FAILURE ;
-    }
-
-    if (!((cols == 16) || (cols == 20))) {
-    	fprintf (stderr, "cols must be 16 or 20\n") ;
-    	return EXIT_FAILURE ;
-    }
-
-    pcf8574Setup(AF_BASE, 0x27) ;
-    pinMode (AF_RW, OUTPUT) ;
-    digitalWrite (AF_RW, LOW) ;        // Not used with wiringPi - always in write mode
-
-    /*
-     * The other control pins are initialised with lcdInit ()
-     */
-    lcdHandle = lcdInit (rows, cols, 4, AF_RS, AF_E, AF_DB4, AF_DB5, AF_DB6, AF_DB7, 0, 0, 0, 0) ;
-    if (lcdHandle < 0) {
-    	fprintf (stderr, "lcdInit failed\n") ;
-    	return -1 ;
-    }
-
-    lcdClear (lcdHandle) ;
-    for (x = 0; x < 20; x++)
-	for (y = 0; y < 4; y++)
-	    lcdbuf[lcdHandle][x][y] = ' ';
-
-    setBacklight (1) ;
-
-    return 0 ;
-}
-
-
-
-void mb_lcdPutchar(const int fd, unsigned char data)
-{
-    struct lcdDataStruct *lcd = lcds[fd];
-
-    /*
-     * Write to our buffer first, then to the wiringPi driver.
-     * Writing to wiringPi updates the cursor position.
-     */
-    lcdbuf[fd][lcd->cx][lcd->cy] = data;
-    lcdPutchar(fd, data);
-}
-
-
-
-void mb_lcdPuts(const int fd, const char *string)
-{
-    while (*string)
-	mb_lcdPutchar (fd, *string++);
-}
-
-
-
-void mb_lcdClear(const int fd)
-{
-    int	x, y;
-
-    lcdClear(fd);
-    for (x = 0; x < 20; x++)
-	for (y = 0; y < 4; y++)
-	    lcdbuf[fd][x][y] = ' ';
-}
-
-
-
-#endif
-
--- a/lib/lock.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*****************************************************************************
- * 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 "../config.h"
-#include "mbselib.h"
-
-/*
- *  Put a lock on this program.
- */
-int lockprog(char *name)
-{
-    char    *tempfile, *lockfile;
-    FILE    *fp;
-    pid_t   oldpid;
-
-    tempfile = calloc(PATH_MAX, sizeof(char));
-    lockfile = calloc(PATH_MAX, sizeof(char));
-
-    snprintf(tempfile, PATH_MAX, "/var/run/%s.tmp", name);
-    snprintf(lockfile, PATH_MAX, "/var/run/%s.pid", name);
-
-    if ((fp = fopen(tempfile, "w")) == NULL) {
-	perror(name);
-	printf("Can't create lockfile \"%s\"\n", tempfile);
-	free(tempfile);
-	free(lockfile);
-	return 1;
-    }
-    fprintf(fp, "%10u\n", getpid());
-    fclose(fp);
-
-    while (TRUE) {
-	if (link(tempfile, lockfile) == 0) {
-	    unlink(tempfile);
-	    free(tempfile);
-	    free(lockfile);
-	    return 0;
-	}
-	if ((fp = fopen(lockfile, "r")) == NULL) {
-	    perror(name);
-	    printf("Can't open lockfile \"%s\"\n", tempfile);
-	    unlink(tempfile);
-	    free(tempfile);
-	    free(lockfile);
-	    return 1;
-	}
-	if (fscanf(fp, "%u", &oldpid) != 1) {
-	    perror(name);
-	    printf("Can't read old pid from \"%s\"\n", tempfile);
-	    fclose(fp);
-	    unlink(tempfile);
-	    free(tempfile);
-	    free(lockfile);
-	    return 1;
-	}
-	fclose(fp);
-	if (kill(oldpid,0) == -1) {
-	    if (errno == ESRCH) {
-		printf("Stale lock found for pid %u\n", oldpid);
-		unlink(lockfile);
-		/* no return, try lock again */  
-	    } else {
-		perror(name);
-		printf("Kill for %u failed\n",oldpid);
-		unlink(tempfile);
-		free(tempfile);
-		free(lockfile);
-		return 1;
-	    }
-	} else {
-	    printf("Another %s is already running, pid=%u\n", name, oldpid);
-	    unlink(tempfile);
-	    free(tempfile);
-	    free(lockfile);
-	    return 1;
-	}
-    }
-}
-
-
-
-void ulockprog(char *name)
-{
-    char	    *lockfile;
-    pid_t	    oldpid;
-    FILE	    *fp;
-
-    lockfile = calloc(PATH_MAX, sizeof(char));
-    snprintf(lockfile, PATH_MAX, "/var/run/%s.pid", name);
-
-    if ((fp = fopen(lockfile, "r")) == NULL) {
-	syslog(LOG_NOTICE, "Can't open lockfile \"%s\"", lockfile);
-	free(lockfile);
-	return;
-    }
-
-    if (fscanf(fp, "%u", &oldpid) != 1) {
-	syslog(LOG_NOTICE, "Can't read old pid from \"%s\"", lockfile);
-	fclose(fp);
-	unlink(lockfile);
-	free(lockfile);
-	return;
-    }
-
-    fclose(fp);
-
-    if (oldpid == getpid()) {
-	(void)unlink(lockfile);
-    }
-
-    free(lockfile);
-}
-
-
--- a/lib/logger.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*****************************************************************************
- * 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 "../config.h"
-#include "mbselib.h"
-
-void logger(char *filename, char *progname, char *data)
-{
-    struct timeval	now;
-    struct tm		ptm;
-    char		*outstr = NULL, *name = NULL;
-    FILE		*logfile;
-
-    name = xstrcpy((char *)"/var/local/log/");
-    name = xstrcat(name, progname);
-    name = xstrcat(name, (char *)"/");
-    name = xstrcat(name, filename);
-
-    gettimeofday(&now, NULL);
-    localtime_r(&now.tv_sec, &ptm);
-
-    if ((logfile = fopen(name, "a+"))) {
-	outstr = calloc(10240, sizeof(char));
-	snprintf(outstr, 10239, "%04d-%02d-%02d %02d:%02d,%s\n", ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, data);
-	fprintf(logfile, outstr);
-	fclose(logfile);
-	free(outstr);
-	outstr = NULL;
-    } else {
-	    syslog(LOG_NOTICE, "logger: cannot open %s for writing", name);
-    }
-
-    free(name);
-    name = NULL;
-}
-
-
--- a/lib/mbselib.h	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-#ifndef	_MBSELIB_H
-#define	_MBSELIB_H
-
-#include "../config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <time.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <getopt.h>
-#include <limits.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <poll.h>
-
-
-/* mosquitto */
-#include <mosquitto.h>
-
-#ifdef HAVE_WIRINGPI_H
-/* wiringPi */
-#include <wiringPi.h>
-#include <pcf8574.h>
-#include <lcd.h>
-
-#endif
-
-#define TRUE 1
-#define FALSE 0
-
-#define MBSE_SS(x) (x)?(x):"(null)"
-
-/* rdconfig.c */
-typedef struct _key_list {
-    char	*key;
-    int		(*prc)(char **);
-    char	**dest;
-} key_list;
-
-typedef struct _w1_therm {
-    struct _w1_therm    *next;
-    char                *master;                /* Master for this device       */
-    int                 bus;                    /* Reserved for ds2482-800      */
-    char                *name;                  /* Name of this device          */
-    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 {
-    struct _rc_switch	*next;
-    char		*address;		/* Address code			*/
-    char		*alias;			/* Friendly name		*/
-} rc_switch;
-
-typedef struct _sys_config {
-    char		*name;			/* Configuration name		*/
-    char		*mosq_host;		/* mosquitto server hostname	*/
-    int			mosq_port;		/* mosquitto server port	*/
-    int			my_port;		/* my client/server port	*/
-    w1_therm		*w1therms;		/* 1-wire temp sensors		*/
-#ifdef HAVE_WIRINGPI_H
-    int			lcd_cols;		/* LCD display columns		*/
-    int			lcd_rows;		/* LCD display rows		*/
-    int			rx433;			/* 433 MHz receiver pin		*/
-    int			tx433;			/* 433 MHz transmitter pin	*/
-    rc_switch		*rcswitch;		/* 433 MHz RC Power switches	*/
-#endif
-} sys_config;
-
-
-void killconfig(void);
-int  rdconfig(char *);
-
-
-/* lock.c */
-int  lockprog(char *);
-void ulockprog(char *);
-
-
-/* xutil.c */
-char *xmalloc(size_t);
-char *xstrcpy(char *);
-char *xstrcat(char *, char *);
-
-
-#ifdef HAVE_WIRINGPI_H
-
-/* lcd-pcf8574.c */
-// Defines for the pcf8574 Pi LCD interface board
-#define AF_BASE         100
-
-#define AF_RS           (AF_BASE + 0)
-#define AF_RW           (AF_BASE + 1)
-#define AF_E            (AF_BASE + 2)
-#define AF_BACKLIGHT    (AF_BASE + 3)
-#define AF_DB4          (AF_BASE + 4)
-#define AF_DB5          (AF_BASE + 5)
-#define AF_DB6          (AF_BASE + 6)
-#define AF_DB7          (AF_BASE + 7)
-
-void setBacklight (int);
-int  initLCD (int, int);
-void mb_lcdPutchar(const int, unsigned char);
-void mb_lcdPuts(const int, const char *);
-void mb_lcdClear(const int);
-
-
-/* logger.c */
-void logger(char *, char *, char *);
-
-
-/* rc-switch.c */
-int  toggleSwitch(char *);
-int  toggleTypeA(char *, char *, bool);
-int  toggleTypeB(int, int, bool);
-int  toggleTypeC(char, int, int, bool);
-int  toggleTypeE(char, int, bool);
-
-void enableReceiveIRQ(int interrupt);
-void enableReceive(void);
-void disableReceive(void);
-bool available(void);
-void resetAvailable(void);
-
-unsigned long getReceivedValue(void);
-unsigned int getReceivedBitlength(void);
-unsigned int getReceivedDelay(void);
-unsigned int getReceivedProtocol(void);
-unsigned int *getReceivedRawdata(void);
-
-void enableTransmit(int);
-void disableTransmit(void);
-
-char *dec2binWzerofill(unsigned long, unsigned int);
-
-
-/* dht11.c */
-void dht11Read(void);
-void dht11Init(int, int, int);
-
-
-#endif
-
-
-#endif
-
--- a/lib/rc-switch.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,956 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2014
- *   
- * Michiel Broek <mbroek at mbse dot eu>
- *
- * This file is part of the mbsePi-apps
- *
- * Based on the Arduino libary for remote control outlet switches.
- * Project home: http://code.google.com/p/rc-switch/
- *
- * 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 "../config.h"
-#include "mbselib.h"
-
-#ifdef HAVE_WIRINGPI_H
-
-
-#define	TYPE_UNDEF	0
-#define	TYPE_MINIMUM	0
-#define	TYPE_A		1
-#define	TYPE_B		2
-#define	TYPE_C		3
-#define	TYPE_D		4
-#define	TYPE_E		3  // TODO: Which Protocol does REV use?
-#define	TYPE_MAXIMUM	4
-
-// Number of maximum High/Low changes per packet.
-// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
-#define RCSWITCH_MAX_CHANGES 67
-
-// i.e. ProtocolCount + 1 (for TYPE_UNDEF)
-#define MAX_PROTOCOLS                   5
-
-#define PROTOCOL_A_SYNC_FACTOR         31
-#define PROTOCOL_A_ZERO_FIRST_CYCLES    1
-#define PROTOCOL_A_ZERO_SECOND_CYCLES   3
-#define PROTOCOL_A_ONE_FIRST_CYCLES     3
-#define PROTOCOL_A_ONE_SECOND_CYCLES    1
-#define PROTOCOL_A_HIGH_FIRST        true
-
-#define PROTOCOL_B_SYNC_FACTOR         10
-#define PROTOCOL_B_ZERO_FIRST_CYCLES    1
-#define PROTOCOL_B_ZERO_SECOND_CYCLES   2
-#define PROTOCOL_B_ONE_FIRST_CYCLES     2
-#define PROTOCOL_B_ONE_SECOND_CYCLES    1
-#define PROTOCOL_B_HIGH_FIRST        true
-
-#define PROTOCOL_C_SYNC_FACTOR         71
-#define PROTOCOL_C_ZERO_FIRST_CYCLES    4
-#define PROTOCOL_C_ZERO_SECOND_CYCLES  11
-#define PROTOCOL_C_ONE_FIRST_CYCLES     9
-#define PROTOCOL_C_ONE_SECOND_CYCLES    6
-#define PROTOCOL_C_HIGH_FIRST        true
-
-// I think, this will work for receive, however, I haven't tested, as I don't own a receiver...
-// As Type D doesn't sync acc. to https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
-// the sync factor is totally undetermined.
-// Malte Diers, 22.11.2013
-#define PROTOCOL_D_SYNC_FACTOR          1
-#define PROTOCOL_D_ZERO_FIRST_CYCLES    1
-#define PROTOCOL_D_ZERO_SECOND_CYCLES   2
-#define PROTOCOL_D_ONE_FIRST_CYCLES     2
-#define PROTOCOL_D_ONE_SECOND_CYCLES    1
-#define PROTOCOL_D_HIGH_FIRST       false
-
-
-#define PROTOCOL3_SYNC_FACTOR   71
-#define PROTOCOL3_0_HIGH_CYCLES  4
-#define PROTOCOL3_0_LOW_CYCLES  11
-#define PROTOCOL3_1_HIGH_CYCLES  9
-#define PROTOCOL3_1_LOW_CYCLES   6
-
-
-
-unsigned long	rcReceivedValue = 0;
-unsigned int	rcReceivedBitlength = 0;
-unsigned int	rcReceivedDelay = 0;
-unsigned int	rcReceivedProtocol = 0;
-int		rcReceiveTolerance = 60;
-int		rcReceiverInterruptPin = -1;
-
-unsigned int	timings[RCSWITCH_MAX_CHANGES];
-int		rcTransmitterPin = -1;
-int		rcPulseLength = 350;	// thermometers 2.4 msec = 2400
-int		rcRepeatTransmit = 10;
-int		rcProtocol = 1;
-
-int		backupProtocol;
-int		backupPulseLength;
-int		backupRepeatTransmit;
-
-
-//const char TYPE_A_CODE[ 6][6]  = { "00000", "10000", "01000", "00100", "00010", "00001"};
-const char TYPE_B_CODE[ 5][5]  = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
-const char TYPE_C_CODE[16][5]  = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0",
-				   "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
-const char TYPE_D_CODE[5][2][9] = { { "11100001", "11110000" }, { "00000000", "00010001" }, { "10000010", "10010011" },
-				    { "11000011", "11010010" }, { "01000001", "01010000" } };
-					/* Type A            Type D */
-const int  PULSE_LENGTH[MAX_PROTOCOLS] 		= { 0, 350, 650, 100, 666, };
-const int  REPEAT_TRANSMIT[MAX_PROTOCOLS] 	= { 0, 10, 10, 10, 4, };
-const int  SYNC_FACTOR[MAX_PROTOCOLS]		= { 0, PROTOCOL_A_SYNC_FACTOR, PROTOCOL_B_SYNC_FACTOR, PROTOCOL_C_SYNC_FACTOR, PROTOCOL_D_SYNC_FACTOR, };
-const int  ZERO_FIRST_CYCLES[MAX_PROTOCOLS]	= { 0, PROTOCOL_A_ZERO_FIRST_CYCLES, PROTOCOL_B_ZERO_FIRST_CYCLES, PROTOCOL_C_ZERO_FIRST_CYCLES, PROTOCOL_D_ZERO_FIRST_CYCLES, };
-const int  ZERO_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_SECOND_CYCLES, PROTOCOL_B_ZERO_SECOND_CYCLES, PROTOCOL_C_ZERO_SECOND_CYCLES, PROTOCOL_D_ZERO_SECOND_CYCLES, };
-const int  ONE_FIRST_CYCLES[MAX_PROTOCOLS]  = { 0, PROTOCOL_A_ONE_FIRST_CYCLES, PROTOCOL_B_ONE_FIRST_CYCLES, PROTOCOL_C_ONE_FIRST_CYCLES, PROTOCOL_D_ONE_FIRST_CYCLES, };
-const int  ONE_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_SECOND_CYCLES, PROTOCOL_B_ONE_SECOND_CYCLES, PROTOCOL_C_ONE_SECOND_CYCLES, PROTOCOL_D_ONE_SECOND_CYCLES, };
-const bool HIGH_FIRST[MAX_PROTOCOLS]        = { 0, PROTOCOL_A_HIGH_FIRST, PROTOCOL_B_HIGH_FIRST, PROTOCOL_C_HIGH_FIRST, PROTOCOL_D_HIGH_FIRST, };
-
-
-char *getCodeWordA(char*, char*, bool);
-char *getCodeWordB(int, int, bool);
-char *getCodeWordC(char, int, int, bool);
-
-char *getCodeWordE(char, int, bool);
-void sendTriState(char*);
-void transmit(int, int, bool);
-void send0(void);
-void send1(void);
-void sendT0(void);
-void sendT1(void);
-void sendTF(void);
-void sendSync(void);
-bool receiveProtocol(int, unsigned int);
-void handleInterrupt(void);
-char *dec2binWcharfill(unsigned long, unsigned int, char);
-
-void setReceiveTolerance(int);
-void setProtocol(int);
-
-void saveProtocol(int);
-void loadProtocol(void);
-
-
-
-/*
- * Sets the protocol to send.
- */
-void setProtocol(int nProtocol) {
-
-    if ((nProtocol < TYPE_MINIMUM) || (nProtocol > TYPE_MAXIMUM)) {
-	return;
-    }
-
-    rcProtocol = nProtocol;
-    rcPulseLength = PULSE_LENGTH[nProtocol];
-    rcRepeatTransmit = REPEAT_TRANSMIT[nProtocol];
-}
-
-
-
-/*
- * Set Receiving Tolerance
- */
-void setReceiveTolerance(int nPercent) {
-    rcReceiveTolerance = nPercent;
-}
-
-
-
-/*
- * Enable transmissions
- *
- * @param nTransmitterPin    Pin to which the sender is connected to
- */
-void enableTransmit(int nTransmitterPin) {
-    rcTransmitterPin = nTransmitterPin;
-    pinMode(rcTransmitterPin, OUTPUT);
-}
-
-
-
-/*
- * Disable transmissions
- */
-void disableTransmit(void) {
-    rcTransmitterPin = -1;
-}
-
-
-
-/*
- * Toggle switch, a command looks like B,3,2,1 which means switch type B,
- * group 3, device 2, status on.
- */
-int toggleSwitch(char *command)
-{
-    static char	*cmd = NULL;
-    char    *s, cType;
-    int	    rc, iGroup, iDevice, iState;
-
-    cmd = xstrcpy(command);
-    s = strtok(cmd, ",\0");
-    cType = s[0];
-
-    if (cType == 'A') {
-
-    } else if (cType == 'B') {
-	s = strtok(NULL, ",\0");
-	rc = sscanf(s, "%d", &iGroup);
-	if (rc != 1)
-	    return 1;
-	s = strtok(NULL, ",\0");
-	rc = sscanf(s, "%d", &iDevice);
-	if (rc != 1)
-	    return 1;
-	s = strtok(NULL, ",\0");
-	rc = sscanf(s, "%d", &iState);
-	if (rc != 1)
-	    return 1;
-	free(cmd);
-	return toggleTypeB(iGroup, iDevice, iState);
-    }
-
-    free(cmd);
-    return 1;
-}
-
-
-
-/*
- * Switch a remote switch on (Type E REV)
- *
- * @param sGroup   Code of the switch group (A,B,C,D)
- * @param nDevice  Number of the switch itself (1..3)
- * @param bStatus  Status to toggle to
- */
-int toggleTypeE(char sGroup, int nDevice, bool bStatus) {
-    sendTriState( getCodeWordE(sGroup, nDevice, bStatus) );
-    return 0;
-}
-
-
-
-/*
- * Switch a remote switch on (Type C Intertechno)
- *
- * @param sFamily  Familycode (a..f)
- * @param nGroup   Number of group (1..4)
- * @param nDevice  Number of device (1..4)
- * @param bStatus  Status to toggle to
- */
-int toggleTypeC(char sFamily, int nGroup, int nDevice, bool bStatus) {
-    char *str = xstrcpy(getCodeWordC(sFamily, nGroup, nDevice, bStatus));
-
-    if (strlen(str) == 0)
-	return 1;
-
-    saveProtocol(TYPE_A);	// ???
-    sendTriState( str );
-    loadProtocol();
-    free(str);
-    return 0;
-}
-
-
-
-/*
- * Switch a remote switch on/off (Type B with two rotary/sliding switches)
- *
- * @param iGroup    Number of the switch group (1..4)
- * @param iDevice   Number of the switch itself (1..4)
- * @param bStatus   Status to toggle to
- */
-int toggleTypeB(int iGroup, int iDevice, bool bStatus)
-{
-    char  *str = xstrcpy(getCodeWordB(iGroup, iDevice, bStatus));
-
-    if (strlen(str) == 0)
-	return 1;
-
-    saveProtocol(TYPE_A);	// They do better with protocol A timings.
-    sendTriState( str );
-    loadProtocol();
-    free(str);
-    return 0;
-}
-
-
-
-/*
- * Switch a remote switch on (Type A with 10 pole DIP switches)
- *
- * @param sGroup    Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param sDevice   Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param bStatus   Status to toggle to
- */
-int toggleTypeA(char* sGroup, char* sDevice, bool bStatus) {
-    char *str = xstrcpy(getCodeWordA(sGroup, sDevice, bStatus));
-
-    if (strlen(str) == 0)
-	return 1;
-
-    saveProtocol(TYPE_A);
-    sendTriState( str );
-    loadProtocol();
-    free(str);
-    return 0;
-}
-
-
-
-/*
- * Returns a char[13], representing the Code Word to be send.
- * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
- * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
- *
- * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
- * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
- * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
- * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
- *
- * @param nAddressCode  Number of the switch group (1..4)
- * @param nChannelCode  Number of the switch itself (1..4)
- * @param bStatus       Wether to switch on (true) or off (false)
- *
- * @return char[13]
- */
-char *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus)
-{
-    int		i, nReturnPos = 0;
-    static char sReturn[13];
-   
-    if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
-    	return '\0';
-    }
-    for (i = 0; i<4; i++) {
-	sReturn[nReturnPos++] = TYPE_B_CODE[nAddressCode][i];
-    }
-
-    for (i = 0; i<4; i++) {
-	sReturn[nReturnPos++] = TYPE_B_CODE[nChannelCode][i];
-    }
-   
-    sReturn[nReturnPos++] = 'F';
-    sReturn[nReturnPos++] = 'F';
-    sReturn[nReturnPos++] = 'F';
-    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
-    sReturn[nReturnPos] = '\0';
-
-    return sReturn;
-}
-
-
-
-/*
- * Returns a char[13], representing the Code Word to be send.
- *
- * getCodeWordA(char*, char*)
- *
- */
-char *getCodeWordA(char* sGroup, char* sDevice, bool bOn)
-{
-    static char sDipSwitches[13];
-    int		i, j = 0;
-
-    for (i=0; i < 5; i++) {
-	sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0';
-    }
-  
-    for (i=0; i < 5; i++) {
-	sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0';
-    }
-
-    if ( bOn ) {
-        sDipSwitches[j++] = '0';
-        sDipSwitches[j++] = 'F';
-    } else {
-        sDipSwitches[j++] = 'F';
-        sDipSwitches[j++] = '0';
-    }
-
-    sDipSwitches[j] = '\0';
-    return sDipSwitches;
-}
-
-
-
-/*
- * Like getCodeWord (Type C = Intertechno)
- */
-char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus)
-{
-    static char sReturn[13];
-    int		i, nReturnPos = 0;
- 
-    if (sFamily < 'a') {
-	// To also enable capital 'A' to 'F'
-	sFamily += 32;
-    }
-
-    if ( sFamily < 'a' || sFamily > 'f' || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
-    	return '\0';
-    }
-  
-    for (i = 0; i<4; i++) {
-    	sReturn[nReturnPos++] = TYPE_C_CODE[ sFamily - 'a' ][i];
-    }
-
-    char *sDeviceGroupCode = dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
-    for (i = 0; i<4; i++) {
-    	sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
-    }
-
-    sReturn[nReturnPos++] = '0';
-    sReturn[nReturnPos++] = 'F';
-    sReturn[nReturnPos++] = 'F';
-    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
-    sReturn[nReturnPos] = '\0';
-
-    return sReturn;
-}
-
-
-
-/*
- * Decoding for the Quigg Switch Type
- *
- * Returns a char[22], representing the States to be send.
- * A Code Word consists of 1 start bit, 12 address bits and 8 command data bits.
- * A Code Bit can have 2 different states: "0" (low), "1" (high)
- *
- * +--------------+--------------------------------+------------------------------+
- * | 1 bits start | 12 bits address (device group) | 8 bits (command/switch data) |
- * |        1     |           110011001100         |             00010001         |
- * +--------------+--------------------------------+------------------------------+
- *
- * Source: https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
- *
- * @param sGroup        12-bit Binary ID of the Device Group
- * @param nDevice       Number of the switch itself (1..4, or 0 to switch the entire Group)
- * @param bStatus       Wether to switch on (true) or off (false)
- *
- * @return char[22]
- */
-char *getCodeWordD(char *sGroup, int nDevice, bool bStatus)
-{
-    static char sReturn[22];
-    int		i, nReturnPos = 0;
-
-    /* Startbit */
-    sReturn[nReturnPos++] = '1';
-
-    /* 12 bit Group */
-    for (i = 0; i < 12; ++i) {
-	sReturn[nReturnPos++] = sGroup[i];
-    }
-
-    /* 8 Bit Device Identifier + Status (undividable!) */
-    for (i = 0; i < 8; ++i) {
-	sReturn[nReturnPos++] = TYPE_D_CODE[nDevice][bStatus][i];
-    }
-    sReturn[nReturnPos] = 0;
-
-    return sReturn;
-}
-
-
-
-/*
- * Decoding for the REV Switch Type
- *
- * Returns a char[13], representing the Tristate to be send.
- * A Code Word consists of 7 address bits and 5 command data bits.
- * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
- *
- * +-------------------------------+--------------------------------+-----------------------+
- * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
- * | A=1FFF B=F1FF C=FF1F D=FFF1   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | on=00010 off=00001    |
- * +-------------------------------+--------------------------------+-----------------------+
- *
- * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
- *
- * @param sGroup        Name of the switch group (A..D, resp. a..d) 
- * @param nDevice       Number of the switch itself (1..3)
- * @param bStatus       Wether to switch on (true) or off (false)
- *
- * @return char[13]
- */
-char *getCodeWordE(char sGroup, int nDevice, bool bStatus){
-    static char sReturn[13];
-    int		i, nReturnPos = 0;
-
-    // Building 4 bits address
-    // (Potential problem if dec2binWcharfill not returning correct string)
-    char *sGroupCode;
-    switch(sGroup){
-        case 'a':
-        case 'A':
-            sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
-        case 'b':
-        case 'B':
-            sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
-        case 'c':
-        case 'C':
-            sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
-        case 'd':
-        case 'D':
-            sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
-        default:
-            return '\0';
-    }
-    
-    for (i = 0; i<4; i++) {
-        sReturn[nReturnPos++] = sGroupCode[i];
-    }
-
-
-    // Building 3 bits address
-    // (Potential problem if dec2binWcharfill not returning correct string)
-    char *sDevice;
-    switch(nDevice) {
-        case 1:
-            sDevice = dec2binWcharfill(4, 3, 'F'); break;
-        case 2:
-            sDevice = dec2binWcharfill(2, 3, 'F'); break;
-        case 3:
-            sDevice = dec2binWcharfill(1, 3, 'F'); break;
-        default:
-            return '\0';
-    }
-
-    for (i = 0; i<3; i++)
-        sReturn[nReturnPos++] = sDevice[i];
-
-    // fill up rest with zeros
-    for (i = 0; i<5; i++)
-        sReturn[nReturnPos++] = '0';
-
-    // encode on or off
-    if (bStatus)
-        sReturn[10] = '1';
-    else
-        sReturn[11] = '1';
-
-    // last position terminate string
-    sReturn[12] = '\0';
-    return sReturn;
-
-}
-
-
-
-/*
- * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
- */
-void sendTriState(char* sCodeWord) {
-    int nRepeat;
-
-    for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) {
-	int i = 0;
-	while (sCodeWord[i] != '\0') {
-	    switch(sCodeWord[i]) {
-		case '0':
-			    sendT0();
-			    break;
-		case 'F':
-			    sendTF();
-			    break;
-		case '1':
-			    sendT1();
-			    break;
-	    }
-	    i++;
-	}
-	sendSync();    
-    }
-}
-
-
-
-/*
-void RCSwitch::send(unsigned long Code, unsigned int length) {
-  this->send( this->dec2binWzerofill(Code, length) );
-}
-
-void RCSwitch::send(char* sCodeWord) {
-  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
-    int i = 0;
-    while (sCodeWord[i] != '\0') {
-      switch(sCodeWord[i]) {
-        case '0':
-          this->send0();
-        break;
-        case '1':
-          this->send1();
-        break;
-      }
-      i++;
-    }
-    this->sendSync();
-  }
-}
-*/
-
-
-void transmit(int nFirstPulses, int nSecondPulses, bool bHighFirst)
-{
-    bool	disabled_Receive = false;
-    int		nReceiverInterrupt_backup = rcReceiverInterruptPin;
-    
-    if (rcTransmitterPin != -1) {
-        if (rcReceiverInterruptPin != -1) {
-            disableReceive();
-            disabled_Receive = true;
-        }
-        digitalWrite(rcTransmitterPin, bHighFirst ? HIGH : LOW);
-	delayMicroseconds( rcPulseLength * nFirstPulses);
-        digitalWrite(rcTransmitterPin, bHighFirst ? LOW : HIGH);
-	delayMicroseconds( rcPulseLength * nSecondPulses);
-        
-        if (disabled_Receive) {
-            enableReceiveIRQ(nReceiverInterrupt_backup);
-        }
-    }
-}
-
-
-
-/*
- * Sends a "0" Bit
- *                       _    
- * Waveform Protocol 1: | |___
- *                       _  
- * Waveform Protocol 2: | |__
- *                       ____
- * Waveform Protocol 3: |    |___________
- */
-//void send0(void) {
-//	if (rcProtocol == 1){
-//		transmit(1,3);
-//	}
-//	else if (rcProtocol == 2) {
-//		transmit(1,2);
-//	}
-//    else if (rcProtocol == 3) {
-//        transmit(4,11);
-//    }
-//}
-
-
-
-/*
- * Sends a "1" Bit
- *                       ___  
- * Waveform Protocol 1: |   |_
- *                       __  
- * Waveform Protocol 2: |  |_
- *                       _________
- * Waveform Protocol 3: |         |______
- */
-//void send1(void) {
-//  	if (rcProtocol == 1){
-//		transmit(3,1);
-//	}
-//	else if (rcProtocol == 2) {
-//		transmit(2,1);
-//	}
-//    else if (rcProtocol == 3) {
-//        transmit(9,6);
-//    }
-//}
-
-
-
-/*
- * Sends a Tri-State "0" Bit
- *            _     _
- * Waveform: | |___| |___
- */
-void sendT0(void) {
-    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
-    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
-//    transmit(1,3,true);
-//    transmit(1,3,true);
-}
-
-
-
-/*
- * Sends a Tri-State "1" Bit
- *            ___   ___
- * Waveform: |   |_|   |_
- */
-void sendT1(void) {
-    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
-    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
-//    transmit(3,1,true);
-//    transmit(3,1,true);
-}
-
-
-
-/*
- * Sends a Tri-State "F" Bit
- *            _     ___
- * Waveform: | |___|   |_
- */
-void sendTF(void) {
-    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);   
-    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
-//    transmit(1,3,true);
-//    transmit(3,1,true);
-}
-
-
-
-/*
- * Sends a "Sync" Bit
- *                       _
- * Waveform Protocol 1: | |_______________________________
- *                       _
- * Waveform Protocol 2: | |__________
- *                       ____
- * Waveform Protocol 3: |    |_______________________________________________________________________
- *
- * Waveform Protocol D: (none, just pause 80 msecs)
- */
-void sendSync(void) {
-
-    if (rcProtocol == TYPE_A) {
-	transmit(1,31,true);
-    } else if (rcProtocol == TYPE_B) {
-	transmit(1,10,true);
-    } else if (rcProtocol == TYPE_C) {
-        transmit(4,71,true);
-    } else if (rcProtocol == TYPE_D) {
-	transmit(0,1,false);
-	delayMicroseconds(80000);
-    }
-}
-
-
-
-/*
- * Enable receiving data
- */
-void enableReceiveIRQ(int Pin) {
-    rcReceiverInterruptPin = Pin;
-    enableReceive();
-}
-
-void enableReceive(void) {
-    if (rcReceiverInterruptPin != -1) {
-	rcReceivedValue = 0;
-	rcReceivedBitlength = 0;
-	wiringPiISR(rcReceiverInterruptPin, INT_EDGE_BOTH, &handleInterrupt);
-    }
-}
-
-
-
-/*
- * Disable receiving data
- */
-void disableReceive() {
-    // wiringPi disable interrupts ???
-    rcReceiverInterruptPin = -1;
-}
-
-
-
-bool available(void) {
-    return rcReceivedValue != 0;
-}
-
-
-
-void resetAvailable(void) {
-    rcReceivedValue = 0;
-}
-
-
-
-unsigned long getReceivedValue(void) {
-    return rcReceivedValue;
-}
-
-
-
-unsigned int getReceivedBitlength(void) {
-    return rcReceivedBitlength;
-}
-
-
-
-unsigned int getReceivedDelay(void) {
-    return rcReceivedDelay;
-}
-
-
-
-unsigned int getReceivedProtocol(void) {
-    return rcReceivedProtocol;
-}
-
-
-
-unsigned int* getReceivedRawdata(void) {
-    return timings;
-}
-
-
-
-/*
- * ASK protool 1
- */
-bool receiveProtocol(int prot, unsigned int changeCount)
-{
-    unsigned long	code = 0;
-    unsigned long	ldelay = timings[0] / SYNC_FACTOR[prot];
-    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
-    int			i;
-
-    if (prot < TYPE_MINIMUM || prot > TYPE_MAXIMUM) {
-	return false;
-    }
-
-    for (i = 1; i<changeCount ; i=i+2) {
-      
-	if (timings[i]   > ldelay * ZERO_FIRST_CYCLES[prot]  - delayTolerance && 
-	    timings[i]   < ldelay * ZERO_FIRST_CYCLES[prot]  + delayTolerance && 
-	    timings[i+1] > ldelay * ZERO_SECOND_CYCLES[prot] - delayTolerance && 
-	    timings[i+1] < ldelay * ZERO_SECOND_CYCLES[prot] + delayTolerance) {
-      	    code = code << 1;
-    	}  else if (timings[i]   > ldelay * ONE_FIRST_CYCLES[prot]  - delayTolerance &&
-		    timings[i]   < ldelay * ONE_FIRST_CYCLES[prot]  + delayTolerance &&
-		    timings[i+1] > ldelay * ONE_SECOND_CYCLES[prot] - delayTolerance &&
-		    timings[i+1] < ldelay * ONE_SECOND_CYCLES[prot] + delayTolerance) {
-	    code+=1;
-	    code = code << 1;
-	} else {
-      	    // Failed
-      	    i = changeCount;
-      	    code = 0;
-    	}
-    }      
-    code = code >> 1;
-    if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
-    	rcReceivedValue = code;
-    	rcReceivedBitlength = changeCount / 2;
-    	rcReceivedDelay = ldelay;
-    	rcReceivedProtocol = prot;
-    }
-
-    return (code != 0);
-}
-
-
-
-void handleInterrupt() {
-
-  static unsigned int duration;
-  static unsigned int changeCount;
-  static unsigned long lastTime;
-  static unsigned int repeatCount;
-
- 
-  long thistime = micros();
-  duration = thistime - lastTime;
-
-  if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) {    
-    repeatCount++;
-    changeCount--;
-    if (repeatCount == 2) {
-      if (receiveProtocol(TYPE_A, changeCount) == false) {
-        if (receiveProtocol(TYPE_B, changeCount) == false) {
-	  if (receiveProtocol(TYPE_C, changeCount) == false) {
-	    if (receiveProtocol(TYPE_D, changeCount) == false) {
-              //failed
-	    }
-	  }
-        }
-      }
-      repeatCount = 0;
-    }
-    changeCount = 0;
-  } else if (duration > 5000) {
-    changeCount = 0;
-  }
-
-  if (changeCount >= RCSWITCH_MAX_CHANGES) {
-    changeCount = 0;
-    repeatCount = 0;
-  }
-  timings[changeCount++] = duration;
-  lastTime = thistime;  
-}
-
-
-
-/*
- * Turns a decimal value to its binary representation
- */
-char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength)
-{
-    return dec2binWcharfill(Dec, bitLength, '0');
-}
-
-char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill)
-{
-    static char		bin[64];
-    unsigned int	i = 0, j;
-
-    while (Dec > 0) {
-    	bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
-    	Dec = Dec >> 1;
-    }
-
-    for (j = 0; j< bitLength; j++) {
-    	if (j >= bitLength - i) {
-      	    bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
-    	} else {
-      	    bin[j] = fill;
-    	}
-    }
-    bin[bitLength] = '\0';
-  
-    return bin;
-}
-
-
-void saveProtocol(int prot)
-{
-    backupProtocol = rcProtocol;
-    backupPulseLength = rcPulseLength;
-    backupRepeatTransmit = rcRepeatTransmit;
-
-    setProtocol(prot);
-}
-
-
-
-void loadProtocol(void)
-{
-    rcProtocol = backupProtocol;
-    rcPulseLength = backupPulseLength;
-    rcRepeatTransmit = backupRepeatTransmit;
-}
-
-
-#endif
-
--- a/lib/rdconfig.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-/*****************************************************************************
- * 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 "../config.h"
-#include "mbselib.h"
-
-
-bool		debug = FALSE;
-static char	*mypath;
-static char	*k, *v;
-static int	linecnt = 0;
-sys_config	Config;			/* System configuration		*/
-
-
-
-static int getstr(char **);
-static int getint(char **);
-static int getw1(char **);
-#ifdef HAVE_WIRINGPI_H
-static int getrcs(char **);
-#endif
-//static int getbyt(char **);
-//static int gethex(char **);
-
-#define XSTR(x) #x
-#define STR(x) XSTR(x)
-
-/*
- * System configuration table
- */
-key_list keytab[] = {
-    {(char *)"mosq_host",	getstr,		&Config.mosq_host},
-    {(char *)"mosq_port",	getint,		(char **)&Config.mosq_port},
-    {(char *)"w1therm",		getw1,		(char **)&Config.w1therms},
-#ifdef HAVE_WIRINGPI_H
-    {(char *)"lcd_cols",	getint,		(char **)&Config.lcd_cols},
-    {(char *)"lcd_rows",	getint,		(char **)&Config.lcd_rows},
-    {(char *)"rx433",		getint,		(char **)&Config.rx433},
-    {(char *)"tx433",		getint,		(char **)&Config.tx433},
-    {(char *)"rcswitch",	getrcs,		(char **)&Config.rcswitch},
-#endif
-    {NULL,			NULL,		NULL}
-};
-
-
-
-void killconfig(void)
-{
-    w1_therm	*tmp1, *old1;
-#ifdef HAVE_WIRINGPI_H
-    rc_switch	*tmp2, *old2;
-#endif
-
-    if (Config.name)
-	free(Config.name);
-    Config.name = NULL;
-
-    if (Config.mosq_host)
-	free(Config.mosq_host);
-    Config.mosq_host= (char *)"localhost";
-    Config.mosq_port = 1883;
-
-    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
-	old1 = tmp1->next;
-	if (tmp1->master)
-	    free(tmp1->master);
-	if (tmp1->name)
-	    free(tmp1->name);
-	if (tmp1->alias)
-	    free(tmp1->alias);
-	free(tmp1);
-    }
-    Config.w1therms = NULL;
-    Config.my_port = 6554;
-
-#ifdef HAVE_WIRINGPI_H
-    Config.lcd_cols = 16;
-    Config.lcd_rows = 2;
-    Config.rx433 = -1;
-    Config.tx433 = -1;
-
-    for (tmp2 = Config.rcswitch; tmp2; tmp2 = old2) {
-	old2 = tmp2->next;
-	if (tmp2->address)
-	    free(tmp2->address);
-	tmp2->address = NULL;
-	if (tmp2->alias)
-	    free(tmp2->alias);
-	tmp2->alias = NULL;
-	free(tmp2);
-    }
-    Config.rcswitch = NULL;
-
-#endif
-}
-
-
-
-int rdconfig(char *config) 
-{
-    char	buf[256], *p;
-    FILE	*fp;
-    int		i, rc = 0;
-
-    killconfig();
-
-    /*
-     * Search config file
-     */
-    mypath = xstrcpy(getenv((char *)"HOME"));
-    mypath = xstrcat(mypath, (char *)"/mbsepi-apps/");
-    mypath = xstrcat(mypath, config);
-    if ((fp = fopen(mypath, "r")) == NULL) {
-	/*
-	 * Not in the users home directory
-	 */
-	free(mypath);
-	mypath = xstrcpy((char *)"/etc/mbsepi-apps/");
-	mypath = xstrcat(mypath, config);
-	if ((fp = fopen(mypath, "r")) == NULL) {
-	    /*
-	     * Try /usr/local/etc
-	     */
-	    free(mypath);
-	    mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/");
-	    mypath = xstrcat(mypath, config);
-	    if ((fp = fopen(mypath, "r")) == NULL) {
-		syslog(LOG_NOTICE, "rdconfig: could not open %s", mypath);
-		return 1;
-	    }
-	}
-    }
-
-    linecnt = 0;
-    while (fgets(buf, sizeof(buf) -1, fp)) {
-	linecnt++;
-	if (*(p = buf + strlen(buf) -1) != '\n') {
-	    syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf);
-	    rc = 1;
-	    break;
-	}
-	*p-- = '\0';
-	while ((p >= buf) && isspace(*p))
-	    *p-- = '\0';
-	k = buf;
-	while (*k && isspace(*k))
-	    k++;
-	p = k;
-	while (*p && !isspace(*p))
-	    p++;
-	*p++='\0';
-	v = p;
-	while (*v && isspace(*v)) 
-	    v++;
-
-	if ((*k == '\0') || (*k == '#')) {
-	    continue;
-	}
-
-	for (i = 0; keytab[i].key; i++)
-	    if (strcasecmp(k,keytab[i].key) == 0)
-		break;
-
-	if (keytab[i].key == NULL) {
-	    syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - unknown keyword", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
-	    rc = 1;
-	    break;
-	} else if ((keytab[i].prc(keytab[i].dest))) {
-	    rc = 1;
-	    break;
-	}
-
-    }
-    fclose(fp);
-
-    free(mypath);
-    mypath = NULL;
-
-    return rc;
-}
-
-
-
-static int getstr(char **dest)
-{
-    if (debug)
-	syslog(LOG_NOTICE, "rdconfig: getstr: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
-
-    *dest = xstrcpy(v);
-    return 0;
-}
-
-
-
-static int getint(char **dest)
-{
-    if (debug)
-	syslog(LOG_NOTICE, "rdconfig: getint: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
-
-    if (strspn(v,"0123456789") != strlen(v)) 
-	syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad numeric", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
-    else 
-	*((int*)dest)=atoi(v);
-    return 0;
-}
-
-
-
-static int getw1(char **dest)
-{
-    char	*p, *q = NULL, *r = NULL;
-    w1_therm	**tmpm;
-    int		rc = 0, tmpp;
-
-    for (p = v; *p && !isspace(*p); p++);
-    if (*p)
-	*p++ = '\0';
-    while (*p && isspace(*p))
-	p++;
-    if (*p == '\0') {
-	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
-	return 1;
-    }
-
-    for (q = p; *q && !isspace(*q); q++);
-    if (*q && isspace(*q)) {
-	if (*q)
-	    *q++ = '\0';
-	while (*q && isspace(*q))
-	    q++;
-
-	for (r = q; *r && !isspace(*r); r++);
-	if (*r)
-	    *r++ = '\0';
-	rc = sscanf(p, "%d", &tmpp);
-	if (rc != 1) {
-	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s is not a integer value", mypath, linecnt, p);
-	    return 1;
-	}
-	if (debug)
-	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s %d %s %s", mypath, linecnt, v, tmpp, q, r);
-    }
-
-    for (tmpm = (w1_therm**)dest; *tmpm; tmpm=&((*tmpm)->next));
-    (*tmpm) = (w1_therm *) xmalloc(sizeof(w1_therm));
-    (*tmpm)->next = NULL;
-    (*tmpm)->master = xstrcpy(v);
-    (*tmpm)->bus = tmpp;
-    (*tmpm)->name = xstrcpy(q);
-    (*tmpm)->alias = xstrcpy(r);
-    (*tmpm)->present = 0;
-    (*tmpm)->lastval = 0;
-    (*tmpm)->update = 0;
-
-    return 0;
-}
-
-
-
-#ifdef HAVE_WIRINGPI_H
-static int getrcs(char **dest)
-{
-    char        *p, *q = NULL, *r = NULL;
-    rc_switch   **tmpm;
-
-    for (p = v; *p && !isspace(*p); p++);
-	if (*p)
-	    *p++ = '\0';
-    while (*p && isspace(*p))
-	p++;
-    if (*p == '\0') {
-	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
-	return 1;
-    }
-
-    for (q = p; *q && !isspace(*q); q++);
-    if (*q && isspace(*q)) {
-	if (*q)
-	    *q++ = '\0';
-	while (*q && isspace(*q))
-	    q++;
-
-	for (r = q; *r && !isspace(*r); r++);
-	if (*r)
-	    *r++ = '\0';
-	if (debug)
-	    syslog(LOG_NOTICE, "rdconfig: getrcs: %s(%d): %s %s", mypath, linecnt, v, p);
-    }
-
-    for (tmpm = (rc_switch**)dest; *tmpm; tmpm=&((*tmpm)->next));
-    (*tmpm) = (rc_switch *) xmalloc(sizeof(rc_switch));
-    (*tmpm)->next = NULL;
-    (*tmpm)->address = xstrcpy(v);
-    (*tmpm)->alias = xstrcpy(p);
-
-    return 0;
-}
-#endif
-
-
-/*
-static int getbyt(char **dest)
-{
-    Log_Msg("[rdconfig] getbyt: %s(%d): %s %s", mypath, linecnt, k, v);
-    if (strspn(v,"0123456789") != strlen(v))
-	Log_Msg("[rdconfig] %s(%d): %s %s - bad numeric", mypath, linecnt, S(k), S(v));
-    else
-	*((Uint8*)dest)=atoi(v);
-    return 0;
-}
-*/
-
-
-/*
-static int gethex(char **dest)
-{
-    unsigned int    val = 0;
-    int		    rc;
-
-    Log_Msg("[rdconfig] gethex: %s(%d): %s %s", mypath, linecnt, k, v);
-    rc = sscanf(v, "%08x", &val);
-    if (rc != 1) {
-	Log_Msg("[rdconfig] %s(%d): %s %s - bad hex value", mypath, linecnt, S(k), S(v));
-	return 1;
-    }
-    *((int*)dest) = val;
-
-    return 0;
-}
-*/
-
-
--- a/lib/xutil.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2008-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 "../config.h"
-#include "mbselib.h"
-
-
-char *xmalloc(size_t size)
-{
-    char *tmp;
-
-    tmp = malloc(size);
-    if (!tmp) 
-	abort();
-			            
-    return tmp;
-}
-
-
-
-char *xstrcpy(char *src)
-{
-    char    *tmp;
-
-    if (src == NULL) 
-	return(NULL);
-    tmp = xmalloc(strlen(src)+1);
-    strcpy(tmp, src);
-    return tmp;
-}
-
-
-
-char *xstrcat(char *src, char *add)
-{
-    char    *tmp;
-    size_t  size = 0;
-
-    if ((add == NULL) || (strlen(add) == 0))
-	return src;
-    if (src)
-	size = strlen(src);
-    size += strlen(add);
-    tmp = xmalloc(size + 1);
-    *tmp = '\0';
-    if (src) {
-	strcpy(tmp, src);
-	free(src);
-    }
-    strcat(tmp, add);
-    return tmp;
-}
-
-
--- a/rc433/Makefile	Sun May 25 16:39:54 2014 +0200
+++ b/rc433/Makefile	Sun May 25 22:06:56 2014 +0200
@@ -2,10 +2,10 @@
 
 include ../Makefile.global
 
-SRCS		= recv.c send.c sniffer.c
-HDRS		= recv.h send.h sniffer.h
-OBJS		= recv.o send.o sniffer.o
-SLIBS		= ../lib/libmbse.a
+SRCS		= $(wildcard *.c)
+HDRS		= $(wildcard *.h)
+OBJS		= $(SRCS:.c=.o)
+SLIBS		= rc-switch.o xutil.o
 TARGET		= recv send sniffer
 OTHER		= Makefile
 
@@ -59,7 +59,9 @@
 
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
-recv.o: ../lib/mbselib.h recv.h
-send.o: ../lib/mbselib.h send.h
-sniffer.o: ../lib/mbselib.h sniffer.h
+recv.o: rc433.h
+send.o: rc433.h
+sniffer.o: rc433.h
+rc-switch.o: rc433.h
+xutil.o: rc433.h
 # End of generated dependencies
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc433/rc-switch.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,955 @@
+/*****************************************************************************
+ * Copyright (C) 2014
+ *   
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of the mbsePi-apps
+ *
+ * Based on the Arduino libary for remote control outlet switches.
+ * Project home: http://code.google.com/p/rc-switch/
+ *
+ * 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 "rc433.h"
+
+#ifdef HAVE_WIRINGPI_H
+
+
+#define	TYPE_UNDEF	0
+#define	TYPE_MINIMUM	0
+#define	TYPE_A		1
+#define	TYPE_B		2
+#define	TYPE_C		3
+#define	TYPE_D		4
+#define	TYPE_E		3  // TODO: Which Protocol does REV use?
+#define	TYPE_MAXIMUM	4
+
+// Number of maximum High/Low changes per packet.
+// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
+#define RCSWITCH_MAX_CHANGES 67
+
+// i.e. ProtocolCount + 1 (for TYPE_UNDEF)
+#define MAX_PROTOCOLS                   5
+
+#define PROTOCOL_A_SYNC_FACTOR         31
+#define PROTOCOL_A_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_A_ZERO_SECOND_CYCLES   3
+#define PROTOCOL_A_ONE_FIRST_CYCLES     3
+#define PROTOCOL_A_ONE_SECOND_CYCLES    1
+#define PROTOCOL_A_HIGH_FIRST        true
+
+#define PROTOCOL_B_SYNC_FACTOR         10
+#define PROTOCOL_B_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_B_ZERO_SECOND_CYCLES   2
+#define PROTOCOL_B_ONE_FIRST_CYCLES     2
+#define PROTOCOL_B_ONE_SECOND_CYCLES    1
+#define PROTOCOL_B_HIGH_FIRST        true
+
+#define PROTOCOL_C_SYNC_FACTOR         71
+#define PROTOCOL_C_ZERO_FIRST_CYCLES    4
+#define PROTOCOL_C_ZERO_SECOND_CYCLES  11
+#define PROTOCOL_C_ONE_FIRST_CYCLES     9
+#define PROTOCOL_C_ONE_SECOND_CYCLES    6
+#define PROTOCOL_C_HIGH_FIRST        true
+
+// I think, this will work for receive, however, I haven't tested, as I don't own a receiver...
+// As Type D doesn't sync acc. to https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
+// the sync factor is totally undetermined.
+// Malte Diers, 22.11.2013
+#define PROTOCOL_D_SYNC_FACTOR          1
+#define PROTOCOL_D_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_D_ZERO_SECOND_CYCLES   2
+#define PROTOCOL_D_ONE_FIRST_CYCLES     2
+#define PROTOCOL_D_ONE_SECOND_CYCLES    1
+#define PROTOCOL_D_HIGH_FIRST       false
+
+
+#define PROTOCOL3_SYNC_FACTOR   71
+#define PROTOCOL3_0_HIGH_CYCLES  4
+#define PROTOCOL3_0_LOW_CYCLES  11
+#define PROTOCOL3_1_HIGH_CYCLES  9
+#define PROTOCOL3_1_LOW_CYCLES   6
+
+
+
+unsigned long	rcReceivedValue = 0;
+unsigned int	rcReceivedBitlength = 0;
+unsigned int	rcReceivedDelay = 0;
+unsigned int	rcReceivedProtocol = 0;
+int		rcReceiveTolerance = 60;
+int		rcReceiverInterruptPin = -1;
+
+unsigned int	timings[RCSWITCH_MAX_CHANGES];
+int		rcTransmitterPin = -1;
+int		rcPulseLength = 350;	// thermometers 2.4 msec = 2400
+int		rcRepeatTransmit = 10;
+int		rcProtocol = 1;
+
+int		backupProtocol;
+int		backupPulseLength;
+int		backupRepeatTransmit;
+
+
+//const char TYPE_A_CODE[ 6][6]  = { "00000", "10000", "01000", "00100", "00010", "00001"};
+const char TYPE_B_CODE[ 5][5]  = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
+const char TYPE_C_CODE[16][5]  = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0",
+				   "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
+const char TYPE_D_CODE[5][2][9] = { { "11100001", "11110000" }, { "00000000", "00010001" }, { "10000010", "10010011" },
+				    { "11000011", "11010010" }, { "01000001", "01010000" } };
+					/* Type A            Type D */
+const int  PULSE_LENGTH[MAX_PROTOCOLS] 		= { 0, 350, 650, 100, 666, };
+const int  REPEAT_TRANSMIT[MAX_PROTOCOLS] 	= { 0, 10, 10, 10, 4, };
+const int  SYNC_FACTOR[MAX_PROTOCOLS]		= { 0, PROTOCOL_A_SYNC_FACTOR, PROTOCOL_B_SYNC_FACTOR, PROTOCOL_C_SYNC_FACTOR, PROTOCOL_D_SYNC_FACTOR, };
+const int  ZERO_FIRST_CYCLES[MAX_PROTOCOLS]	= { 0, PROTOCOL_A_ZERO_FIRST_CYCLES, PROTOCOL_B_ZERO_FIRST_CYCLES, PROTOCOL_C_ZERO_FIRST_CYCLES, PROTOCOL_D_ZERO_FIRST_CYCLES, };
+const int  ZERO_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_SECOND_CYCLES, PROTOCOL_B_ZERO_SECOND_CYCLES, PROTOCOL_C_ZERO_SECOND_CYCLES, PROTOCOL_D_ZERO_SECOND_CYCLES, };
+const int  ONE_FIRST_CYCLES[MAX_PROTOCOLS]  = { 0, PROTOCOL_A_ONE_FIRST_CYCLES, PROTOCOL_B_ONE_FIRST_CYCLES, PROTOCOL_C_ONE_FIRST_CYCLES, PROTOCOL_D_ONE_FIRST_CYCLES, };
+const int  ONE_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_SECOND_CYCLES, PROTOCOL_B_ONE_SECOND_CYCLES, PROTOCOL_C_ONE_SECOND_CYCLES, PROTOCOL_D_ONE_SECOND_CYCLES, };
+const bool HIGH_FIRST[MAX_PROTOCOLS]        = { 0, PROTOCOL_A_HIGH_FIRST, PROTOCOL_B_HIGH_FIRST, PROTOCOL_C_HIGH_FIRST, PROTOCOL_D_HIGH_FIRST, };
+
+
+char *getCodeWordA(char*, char*, bool);
+char *getCodeWordB(int, int, bool);
+char *getCodeWordC(char, int, int, bool);
+
+char *getCodeWordE(char, int, bool);
+void sendTriState(char*);
+void transmit(int, int, bool);
+void send0(void);
+void send1(void);
+void sendT0(void);
+void sendT1(void);
+void sendTF(void);
+void sendSync(void);
+bool receiveProtocol(int, unsigned int);
+void handleInterrupt(void);
+char *dec2binWcharfill(unsigned long, unsigned int, char);
+
+void setReceiveTolerance(int);
+void setProtocol(int);
+
+void saveProtocol(int);
+void loadProtocol(void);
+
+
+
+/*
+ * Sets the protocol to send.
+ */
+void setProtocol(int nProtocol) {
+
+    if ((nProtocol < TYPE_MINIMUM) || (nProtocol > TYPE_MAXIMUM)) {
+	return;
+    }
+
+    rcProtocol = nProtocol;
+    rcPulseLength = PULSE_LENGTH[nProtocol];
+    rcRepeatTransmit = REPEAT_TRANSMIT[nProtocol];
+}
+
+
+
+/*
+ * Set Receiving Tolerance
+ */
+void setReceiveTolerance(int nPercent) {
+    rcReceiveTolerance = nPercent;
+}
+
+
+
+/*
+ * Enable transmissions
+ *
+ * @param nTransmitterPin    Pin to which the sender is connected to
+ */
+void enableTransmit(int nTransmitterPin) {
+    rcTransmitterPin = nTransmitterPin;
+    pinMode(rcTransmitterPin, OUTPUT);
+}
+
+
+
+/*
+ * Disable transmissions
+ */
+void disableTransmit(void) {
+    rcTransmitterPin = -1;
+}
+
+
+
+/*
+ * Toggle switch, a command looks like B,3,2,1 which means switch type B,
+ * group 3, device 2, status on.
+ */
+int toggleSwitch(char *command)
+{
+    static char	*cmd = NULL;
+    char    *s, cType;
+    int	    rc, iGroup, iDevice, iState;
+
+    cmd = xstrcpy(command);
+    s = strtok(cmd, ",\0");
+    cType = s[0];
+
+    if (cType == 'A') {
+
+    } else if (cType == 'B') {
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iGroup);
+	if (rc != 1)
+	    return 1;
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iDevice);
+	if (rc != 1)
+	    return 1;
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iState);
+	if (rc != 1)
+	    return 1;
+	free(cmd);
+	return toggleTypeB(iGroup, iDevice, iState);
+    }
+
+    free(cmd);
+    return 1;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type E REV)
+ *
+ * @param sGroup   Code of the switch group (A,B,C,D)
+ * @param nDevice  Number of the switch itself (1..3)
+ * @param bStatus  Status to toggle to
+ */
+int toggleTypeE(char sGroup, int nDevice, bool bStatus) {
+    sendTriState( getCodeWordE(sGroup, nDevice, bStatus) );
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type C Intertechno)
+ *
+ * @param sFamily  Familycode (a..f)
+ * @param nGroup   Number of group (1..4)
+ * @param nDevice  Number of device (1..4)
+ * @param bStatus  Status to toggle to
+ */
+int toggleTypeC(char sFamily, int nGroup, int nDevice, bool bStatus) {
+    char *str = xstrcpy(getCodeWordC(sFamily, nGroup, nDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);	// ???
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on/off (Type B with two rotary/sliding switches)
+ *
+ * @param iGroup    Number of the switch group (1..4)
+ * @param iDevice   Number of the switch itself (1..4)
+ * @param bStatus   Status to toggle to
+ */
+int toggleTypeB(int iGroup, int iDevice, bool bStatus)
+{
+    char  *str = xstrcpy(getCodeWordB(iGroup, iDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);	// They do better with protocol A timings.
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
+ *
+ * @param sGroup    Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
+ * @param sDevice   Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
+ * @param bStatus   Status to toggle to
+ */
+int toggleTypeA(char* sGroup, char* sDevice, bool bStatus) {
+    char *str = xstrcpy(getCodeWordA(sGroup, sDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Returns a char[13], representing the Code Word to be send.
+ * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
+ * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
+ *
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
+ * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ *
+ * @param nAddressCode  Number of the switch group (1..4)
+ * @param nChannelCode  Number of the switch itself (1..4)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+char *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus)
+{
+    int		i, nReturnPos = 0;
+    static char sReturn[13];
+   
+    if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
+    	return '\0';
+    }
+    for (i = 0; i<4; i++) {
+	sReturn[nReturnPos++] = TYPE_B_CODE[nAddressCode][i];
+    }
+
+    for (i = 0; i<4; i++) {
+	sReturn[nReturnPos++] = TYPE_B_CODE[nChannelCode][i];
+    }
+   
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
+    sReturn[nReturnPos] = '\0';
+
+    return sReturn;
+}
+
+
+
+/*
+ * Returns a char[13], representing the Code Word to be send.
+ *
+ * getCodeWordA(char*, char*)
+ *
+ */
+char *getCodeWordA(char* sGroup, char* sDevice, bool bOn)
+{
+    static char sDipSwitches[13];
+    int		i, j = 0;
+
+    for (i=0; i < 5; i++) {
+	sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0';
+    }
+  
+    for (i=0; i < 5; i++) {
+	sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0';
+    }
+
+    if ( bOn ) {
+        sDipSwitches[j++] = '0';
+        sDipSwitches[j++] = 'F';
+    } else {
+        sDipSwitches[j++] = 'F';
+        sDipSwitches[j++] = '0';
+    }
+
+    sDipSwitches[j] = '\0';
+    return sDipSwitches;
+}
+
+
+
+/*
+ * Like getCodeWord (Type C = Intertechno)
+ */
+char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus)
+{
+    static char sReturn[13];
+    int		i, nReturnPos = 0;
+ 
+    if (sFamily < 'a') {
+	// To also enable capital 'A' to 'F'
+	sFamily += 32;
+    }
+
+    if ( sFamily < 'a' || sFamily > 'f' || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
+    	return '\0';
+    }
+  
+    for (i = 0; i<4; i++) {
+    	sReturn[nReturnPos++] = TYPE_C_CODE[ sFamily - 'a' ][i];
+    }
+
+    char *sDeviceGroupCode = dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
+    for (i = 0; i<4; i++) {
+    	sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
+    }
+
+    sReturn[nReturnPos++] = '0';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
+    sReturn[nReturnPos] = '\0';
+
+    return sReturn;
+}
+
+
+
+/*
+ * Decoding for the Quigg Switch Type
+ *
+ * Returns a char[22], representing the States to be send.
+ * A Code Word consists of 1 start bit, 12 address bits and 8 command data bits.
+ * A Code Bit can have 2 different states: "0" (low), "1" (high)
+ *
+ * +--------------+--------------------------------+------------------------------+
+ * | 1 bits start | 12 bits address (device group) | 8 bits (command/switch data) |
+ * |        1     |           110011001100         |             00010001         |
+ * +--------------+--------------------------------+------------------------------+
+ *
+ * Source: https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
+ *
+ * @param sGroup        12-bit Binary ID of the Device Group
+ * @param nDevice       Number of the switch itself (1..4, or 0 to switch the entire Group)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[22]
+ */
+char *getCodeWordD(char *sGroup, int nDevice, bool bStatus)
+{
+    static char sReturn[22];
+    int		i, nReturnPos = 0;
+
+    /* Startbit */
+    sReturn[nReturnPos++] = '1';
+
+    /* 12 bit Group */
+    for (i = 0; i < 12; ++i) {
+	sReturn[nReturnPos++] = sGroup[i];
+    }
+
+    /* 8 Bit Device Identifier + Status (undividable!) */
+    for (i = 0; i < 8; ++i) {
+	sReturn[nReturnPos++] = TYPE_D_CODE[nDevice][bStatus][i];
+    }
+    sReturn[nReturnPos] = 0;
+
+    return sReturn;
+}
+
+
+
+/*
+ * Decoding for the REV Switch Type
+ *
+ * Returns a char[13], representing the Tristate to be send.
+ * A Code Word consists of 7 address bits and 5 command data bits.
+ * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
+ *
+ * +-------------------------------+--------------------------------+-----------------------+
+ * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
+ * | A=1FFF B=F1FF C=FF1F D=FFF1   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | on=00010 off=00001    |
+ * +-------------------------------+--------------------------------+-----------------------+
+ *
+ * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
+ *
+ * @param sGroup        Name of the switch group (A..D, resp. a..d) 
+ * @param nDevice       Number of the switch itself (1..3)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+char *getCodeWordE(char sGroup, int nDevice, bool bStatus){
+    static char sReturn[13];
+    int		i, nReturnPos = 0;
+
+    // Building 4 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sGroupCode;
+    switch(sGroup){
+        case 'a':
+        case 'A':
+            sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
+        case 'b':
+        case 'B':
+            sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
+        case 'c':
+        case 'C':
+            sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
+        case 'd':
+        case 'D':
+            sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
+        default:
+            return '\0';
+    }
+    
+    for (i = 0; i<4; i++) {
+        sReturn[nReturnPos++] = sGroupCode[i];
+    }
+
+
+    // Building 3 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sDevice;
+    switch(nDevice) {
+        case 1:
+            sDevice = dec2binWcharfill(4, 3, 'F'); break;
+        case 2:
+            sDevice = dec2binWcharfill(2, 3, 'F'); break;
+        case 3:
+            sDevice = dec2binWcharfill(1, 3, 'F'); break;
+        default:
+            return '\0';
+    }
+
+    for (i = 0; i<3; i++)
+        sReturn[nReturnPos++] = sDevice[i];
+
+    // fill up rest with zeros
+    for (i = 0; i<5; i++)
+        sReturn[nReturnPos++] = '0';
+
+    // encode on or off
+    if (bStatus)
+        sReturn[10] = '1';
+    else
+        sReturn[11] = '1';
+
+    // last position terminate string
+    sReturn[12] = '\0';
+    return sReturn;
+
+}
+
+
+
+/*
+ * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
+ */
+void sendTriState(char* sCodeWord) {
+    int nRepeat;
+
+    for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) {
+	int i = 0;
+	while (sCodeWord[i] != '\0') {
+	    switch(sCodeWord[i]) {
+		case '0':
+			    sendT0();
+			    break;
+		case 'F':
+			    sendTF();
+			    break;
+		case '1':
+			    sendT1();
+			    break;
+	    }
+	    i++;
+	}
+	sendSync();    
+    }
+}
+
+
+
+/*
+void RCSwitch::send(unsigned long Code, unsigned int length) {
+  this->send( this->dec2binWzerofill(Code, length) );
+}
+
+void RCSwitch::send(char* sCodeWord) {
+  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
+    int i = 0;
+    while (sCodeWord[i] != '\0') {
+      switch(sCodeWord[i]) {
+        case '0':
+          this->send0();
+        break;
+        case '1':
+          this->send1();
+        break;
+      }
+      i++;
+    }
+    this->sendSync();
+  }
+}
+*/
+
+
+void transmit(int nFirstPulses, int nSecondPulses, bool bHighFirst)
+{
+    bool	disabled_Receive = false;
+    int		nReceiverInterrupt_backup = rcReceiverInterruptPin;
+    
+    if (rcTransmitterPin != -1) {
+        if (rcReceiverInterruptPin != -1) {
+            disableReceive();
+            disabled_Receive = true;
+        }
+        digitalWrite(rcTransmitterPin, bHighFirst ? HIGH : LOW);
+	delayMicroseconds( rcPulseLength * nFirstPulses);
+        digitalWrite(rcTransmitterPin, bHighFirst ? LOW : HIGH);
+	delayMicroseconds( rcPulseLength * nSecondPulses);
+        
+        if (disabled_Receive) {
+            enableReceiveIRQ(nReceiverInterrupt_backup);
+        }
+    }
+}
+
+
+
+/*
+ * Sends a "0" Bit
+ *                       _    
+ * Waveform Protocol 1: | |___
+ *                       _  
+ * Waveform Protocol 2: | |__
+ *                       ____
+ * Waveform Protocol 3: |    |___________
+ */
+//void send0(void) {
+//	if (rcProtocol == 1){
+//		transmit(1,3);
+//	}
+//	else if (rcProtocol == 2) {
+//		transmit(1,2);
+//	}
+//    else if (rcProtocol == 3) {
+//        transmit(4,11);
+//    }
+//}
+
+
+
+/*
+ * Sends a "1" Bit
+ *                       ___  
+ * Waveform Protocol 1: |   |_
+ *                       __  
+ * Waveform Protocol 2: |  |_
+ *                       _________
+ * Waveform Protocol 3: |         |______
+ */
+//void send1(void) {
+//  	if (rcProtocol == 1){
+//		transmit(3,1);
+//	}
+//	else if (rcProtocol == 2) {
+//		transmit(2,1);
+//	}
+//    else if (rcProtocol == 3) {
+//        transmit(9,6);
+//    }
+//}
+
+
+
+/*
+ * Sends a Tri-State "0" Bit
+ *            _     _
+ * Waveform: | |___| |___
+ */
+void sendT0(void) {
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(1,3,true);
+//    transmit(1,3,true);
+}
+
+
+
+/*
+ * Sends a Tri-State "1" Bit
+ *            ___   ___
+ * Waveform: |   |_|   |_
+ */
+void sendT1(void) {
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(3,1,true);
+//    transmit(3,1,true);
+}
+
+
+
+/*
+ * Sends a Tri-State "F" Bit
+ *            _     ___
+ * Waveform: | |___|   |_
+ */
+void sendTF(void) {
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);   
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(1,3,true);
+//    transmit(3,1,true);
+}
+
+
+
+/*
+ * Sends a "Sync" Bit
+ *                       _
+ * Waveform Protocol 1: | |_______________________________
+ *                       _
+ * Waveform Protocol 2: | |__________
+ *                       ____
+ * Waveform Protocol 3: |    |_______________________________________________________________________
+ *
+ * Waveform Protocol D: (none, just pause 80 msecs)
+ */
+void sendSync(void) {
+
+    if (rcProtocol == TYPE_A) {
+	transmit(1,31,true);
+    } else if (rcProtocol == TYPE_B) {
+	transmit(1,10,true);
+    } else if (rcProtocol == TYPE_C) {
+        transmit(4,71,true);
+    } else if (rcProtocol == TYPE_D) {
+	transmit(0,1,false);
+	delayMicroseconds(80000);
+    }
+}
+
+
+
+/*
+ * Enable receiving data
+ */
+void enableReceiveIRQ(int Pin) {
+    rcReceiverInterruptPin = Pin;
+    enableReceive();
+}
+
+void enableReceive(void) {
+    if (rcReceiverInterruptPin != -1) {
+	rcReceivedValue = 0;
+	rcReceivedBitlength = 0;
+	wiringPiISR(rcReceiverInterruptPin, INT_EDGE_BOTH, &handleInterrupt);
+    }
+}
+
+
+
+/*
+ * Disable receiving data
+ */
+void disableReceive() {
+    // wiringPi disable interrupts ???
+    rcReceiverInterruptPin = -1;
+}
+
+
+
+bool available(void) {
+    return rcReceivedValue != 0;
+}
+
+
+
+void resetAvailable(void) {
+    rcReceivedValue = 0;
+}
+
+
+
+unsigned long getReceivedValue(void) {
+    return rcReceivedValue;
+}
+
+
+
+unsigned int getReceivedBitlength(void) {
+    return rcReceivedBitlength;
+}
+
+
+
+unsigned int getReceivedDelay(void) {
+    return rcReceivedDelay;
+}
+
+
+
+unsigned int getReceivedProtocol(void) {
+    return rcReceivedProtocol;
+}
+
+
+
+unsigned int* getReceivedRawdata(void) {
+    return timings;
+}
+
+
+
+/*
+ * ASK protool 1
+ */
+bool receiveProtocol(int prot, unsigned int changeCount)
+{
+    unsigned long	code = 0;
+    unsigned long	ldelay = timings[0] / SYNC_FACTOR[prot];
+    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
+    int			i;
+
+    if (prot < TYPE_MINIMUM || prot > TYPE_MAXIMUM) {
+	return false;
+    }
+
+    for (i = 1; i<changeCount ; i=i+2) {
+      
+	if (timings[i]   > ldelay * ZERO_FIRST_CYCLES[prot]  - delayTolerance && 
+	    timings[i]   < ldelay * ZERO_FIRST_CYCLES[prot]  + delayTolerance && 
+	    timings[i+1] > ldelay * ZERO_SECOND_CYCLES[prot] - delayTolerance && 
+	    timings[i+1] < ldelay * ZERO_SECOND_CYCLES[prot] + delayTolerance) {
+      	    code = code << 1;
+    	}  else if (timings[i]   > ldelay * ONE_FIRST_CYCLES[prot]  - delayTolerance &&
+		    timings[i]   < ldelay * ONE_FIRST_CYCLES[prot]  + delayTolerance &&
+		    timings[i+1] > ldelay * ONE_SECOND_CYCLES[prot] - delayTolerance &&
+		    timings[i+1] < ldelay * ONE_SECOND_CYCLES[prot] + delayTolerance) {
+	    code+=1;
+	    code = code << 1;
+	} else {
+      	    // Failed
+      	    i = changeCount;
+      	    code = 0;
+    	}
+    }      
+    code = code >> 1;
+    if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
+    	rcReceivedValue = code;
+    	rcReceivedBitlength = changeCount / 2;
+    	rcReceivedDelay = ldelay;
+    	rcReceivedProtocol = prot;
+    }
+
+    return (code != 0);
+}
+
+
+
+void handleInterrupt() {
+
+  static unsigned int duration;
+  static unsigned int changeCount;
+  static unsigned long lastTime;
+  static unsigned int repeatCount;
+
+ 
+  long thistime = micros();
+  duration = thistime - lastTime;
+
+  if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) {    
+    repeatCount++;
+    changeCount--;
+    if (repeatCount == 2) {
+      if (receiveProtocol(TYPE_A, changeCount) == false) {
+        if (receiveProtocol(TYPE_B, changeCount) == false) {
+	  if (receiveProtocol(TYPE_C, changeCount) == false) {
+	    if (receiveProtocol(TYPE_D, changeCount) == false) {
+              //failed
+	    }
+	  }
+        }
+      }
+      repeatCount = 0;
+    }
+    changeCount = 0;
+  } else if (duration > 5000) {
+    changeCount = 0;
+  }
+
+  if (changeCount >= RCSWITCH_MAX_CHANGES) {
+    changeCount = 0;
+    repeatCount = 0;
+  }
+  timings[changeCount++] = duration;
+  lastTime = thistime;  
+}
+
+
+
+/*
+ * Turns a decimal value to its binary representation
+ */
+char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength)
+{
+    return dec2binWcharfill(Dec, bitLength, '0');
+}
+
+char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill)
+{
+    static char		bin[64];
+    unsigned int	i = 0, j;
+
+    while (Dec > 0) {
+    	bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
+    	Dec = Dec >> 1;
+    }
+
+    for (j = 0; j< bitLength; j++) {
+    	if (j >= bitLength - i) {
+      	    bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
+    	} else {
+      	    bin[j] = fill;
+    	}
+    }
+    bin[bitLength] = '\0';
+  
+    return bin;
+}
+
+
+void saveProtocol(int prot)
+{
+    backupProtocol = rcProtocol;
+    backupPulseLength = rcPulseLength;
+    backupRepeatTransmit = rcRepeatTransmit;
+
+    setProtocol(prot);
+}
+
+
+
+void loadProtocol(void)
+{
+    rcProtocol = backupProtocol;
+    rcPulseLength = backupPulseLength;
+    rcRepeatTransmit = backupRepeatTransmit;
+}
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc433/rc433.h	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,54 @@
+#ifndef	_RC433_H
+#define	_RC433_H
+
+#define TRUE 1
+#define FALSE 0
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+
+/* wiringPi */
+#include <wiringPi.h>
+
+
+/* rc-switch.c */
+int  toggleSwitch(char *);
+int  toggleTypeA(char *, char *, bool);
+int  toggleTypeB(int, int, bool);
+int  toggleTypeC(char, int, int, bool);
+int  toggleTypeE(char, int, bool);
+
+void enableReceiveIRQ(int interrupt);
+void enableReceive(void);
+void disableReceive(void);
+bool available(void);
+void resetAvailable(void);
+
+unsigned long getReceivedValue(void);
+unsigned int getReceivedBitlength(void);
+unsigned int getReceivedDelay(void);
+unsigned int getReceivedProtocol(void);
+unsigned int *getReceivedRawdata(void);
+
+void enableTransmit(int);
+void disableTransmit(void);
+
+char *dec2binWzerofill(unsigned long, unsigned int);
+
+
+/* xutil.c */
+char *xmalloc(size_t);
+char *xstrcpy(char *);
+char *xstrcat(char *, char *);
+
+
+#endif
--- a/rc433/recv.c	Sun May 25 16:39:54 2014 +0200
+++ b/rc433/recv.c	Sun May 25 22:06:56 2014 +0200
@@ -20,8 +20,7 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
-#include "../lib/mbselib.h"
-#include "recv.h"
+#include "rc433.h"
 
 
 #ifdef HAVE_WIRINGPI_H
--- a/rc433/recv.h	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-#ifndef	_RECV_H
-#define	_RECV_H
-
-
-#define TRUE 1
-#define FALSE 0
-
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc433/xutil.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * Copyright (C) 2008-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 "rc433.h"
+
+
+char *xmalloc(size_t size)
+{
+    char *tmp;
+
+    tmp = malloc(size);
+    if (!tmp) 
+	abort();
+			            
+    return tmp;
+}
+
+
+
+char *xstrcpy(char *src)
+{
+    char    *tmp;
+
+    if (src == NULL) 
+	return(NULL);
+    tmp = xmalloc(strlen(src)+1);
+    strcpy(tmp, src);
+    return tmp;
+}
+
+
+
+char *xstrcat(char *src, char *add)
+{
+    char    *tmp;
+    size_t  size = 0;
+
+    if ((add == NULL) || (strlen(add) == 0))
+	return src;
+    if (src)
+	size = strlen(src);
+    size += strlen(add);
+    tmp = xmalloc(size + 1);
+    *tmp = '\0';
+    if (src) {
+	strcpy(tmp, src);
+	free(src);
+    }
+    strcat(tmp, add);
+    return tmp;
+}
+
+
--- a/thermferm/Makefile	Sun May 25 16:39:54 2014 +0200
+++ b/thermferm/Makefile	Sun May 25 22:06:56 2014 +0200
@@ -5,7 +5,7 @@
 SRCS		= $(wildcard *.c)
 HDRS		= $(wildcard *.h)
 OBJS		= $(SRCS:.c=.o)
-SLIBS		= -lpthread ../lib/libmbse.a
+SLIBS		= -lpthread
 TARGET		= thermferm
 OTHER		= Makefile
 
@@ -54,8 +54,13 @@
 
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
-thermferm.o: ../lib/mbselib.h thermferm.h sensors.h server.h
-sensors.o: ../lib/mbselib.h sensors.h
-mosquitto.o: ../lib/mbselib.h mosquitto.h
-server.o: ../lib/mbselib.h server.h thermferm.h
+thermferm.o: thermferm.h
+sensors.o: thermferm.h
+server.o: thermferm.h
+xutil.o: thermferm.h
+lcd-pcf8574.o: thermferm.h
+rdconfig.o: thermferm.h
+lock.o: thermferm.h
+logger.o: thermferm.h
+rc-switch.o: thermferm.h
 # End of generated dependencies
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/lcd-pcf8574.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,142 @@
+/*
+ * lcd-pcf8574.c:
+ *	Text-based LCD driver library code
+ *	This is designed to drive the HD44780U LCD display connected via
+ *	a "LCM1602 IIC  A0 A1 A2" board with a PCF8574 I2C controller.
+ *
+ * Copyright (c) 2012-2013 Gordon Henderson.
+ * Copyright (c) 2014 Michiel Broek.
+ ***********************************************************************
+ *
+ *    mbsePi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    mbsePi 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 Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public License
+ *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include "thermferm.h"
+
+#ifdef HAVE_WIRINGPI_H
+
+int			lcdHandle;
+unsigned char		lcdbuf[MAX_LCDS][20][4];
+
+struct lcdDataStruct
+{
+    int bits, rows, cols ;
+    int rsPin, strbPin ;
+    int dataPins [8] ;
+    int cx, cy ;
+};
+extern struct lcdDataStruct	*lcds [MAX_LCDS];
+
+
+/*
+ * Some LCD functions are extended shadow copies of the wiringPi functions.
+ * The difference is that the lcdbuf will be updated with the contents on
+ * the hardware display. This copy can then be used for a remote display
+ */
+
+
+/*
+ * setBacklight:
+ *********************************************************************************
+ */
+
+void setBacklight (int value)
+{
+  pinMode (AF_BACKLIGHT, OUTPUT) ;
+  digitalWrite (AF_BACKLIGHT, (value & 1)) ;
+}
+
+
+
+/*
+ * initLCD:
+ *********************************************************************************
+ */
+
+int initLCD (int cols, int rows)
+{
+    int	x, y;
+
+    if (!((rows == 1) || (rows == 2) || (rows == 4))) {
+    	fprintf (stderr, "rows must be 1, 2 or 4\n") ;
+    	return EXIT_FAILURE ;
+    }
+
+    if (!((cols == 16) || (cols == 20))) {
+    	fprintf (stderr, "cols must be 16 or 20\n") ;
+    	return EXIT_FAILURE ;
+    }
+
+    pcf8574Setup(AF_BASE, 0x27) ;
+    pinMode (AF_RW, OUTPUT) ;
+    digitalWrite (AF_RW, LOW) ;        // Not used with wiringPi - always in write mode
+
+    /*
+     * The other control pins are initialised with lcdInit ()
+     */
+    lcdHandle = lcdInit (rows, cols, 4, AF_RS, AF_E, AF_DB4, AF_DB5, AF_DB6, AF_DB7, 0, 0, 0, 0) ;
+    if (lcdHandle < 0) {
+    	fprintf (stderr, "lcdInit failed\n") ;
+    	return -1 ;
+    }
+
+    lcdClear (lcdHandle) ;
+    for (x = 0; x < 20; x++)
+	for (y = 0; y < 4; y++)
+	    lcdbuf[lcdHandle][x][y] = ' ';
+
+    setBacklight (1) ;
+
+    return 0 ;
+}
+
+
+
+void mb_lcdPutchar(const int fd, unsigned char data)
+{
+    struct lcdDataStruct *lcd = lcds[fd];
+
+    /*
+     * Write to our buffer first, then to the wiringPi driver.
+     * Writing to wiringPi updates the cursor position.
+     */
+    lcdbuf[fd][lcd->cx][lcd->cy] = data;
+    lcdPutchar(fd, data);
+}
+
+
+
+void mb_lcdPuts(const int fd, const char *string)
+{
+    while (*string)
+	mb_lcdPutchar (fd, *string++);
+}
+
+
+
+void mb_lcdClear(const int fd)
+{
+    int	x, y;
+
+    lcdClear(fd);
+    for (x = 0; x < 20; x++)
+	for (y = 0; y < 4; y++)
+	    lcdbuf[fd][x][y] = ' ';
+}
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/lock.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,132 @@
+/*****************************************************************************
+ * 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"
+
+/*
+ *  Put a lock on this program.
+ */
+int lockprog(char *name)
+{
+    char    *tempfile, *lockfile;
+    FILE    *fp;
+    pid_t   oldpid;
+
+    tempfile = calloc(PATH_MAX, sizeof(char));
+    lockfile = calloc(PATH_MAX, sizeof(char));
+
+    snprintf(tempfile, PATH_MAX, "/var/run/%s.tmp", name);
+    snprintf(lockfile, PATH_MAX, "/var/run/%s.pid", name);
+
+    if ((fp = fopen(tempfile, "w")) == NULL) {
+	perror(name);
+	printf("Can't create lockfile \"%s\"\n", tempfile);
+	free(tempfile);
+	free(lockfile);
+	return 1;
+    }
+    fprintf(fp, "%10u\n", getpid());
+    fclose(fp);
+
+    while (TRUE) {
+	if (link(tempfile, lockfile) == 0) {
+	    unlink(tempfile);
+	    free(tempfile);
+	    free(lockfile);
+	    return 0;
+	}
+	if ((fp = fopen(lockfile, "r")) == NULL) {
+	    perror(name);
+	    printf("Can't open lockfile \"%s\"\n", tempfile);
+	    unlink(tempfile);
+	    free(tempfile);
+	    free(lockfile);
+	    return 1;
+	}
+	if (fscanf(fp, "%u", &oldpid) != 1) {
+	    perror(name);
+	    printf("Can't read old pid from \"%s\"\n", tempfile);
+	    fclose(fp);
+	    unlink(tempfile);
+	    free(tempfile);
+	    free(lockfile);
+	    return 1;
+	}
+	fclose(fp);
+	if (kill(oldpid,0) == -1) {
+	    if (errno == ESRCH) {
+		printf("Stale lock found for pid %u\n", oldpid);
+		unlink(lockfile);
+		/* no return, try lock again */  
+	    } else {
+		perror(name);
+		printf("Kill for %u failed\n",oldpid);
+		unlink(tempfile);
+		free(tempfile);
+		free(lockfile);
+		return 1;
+	    }
+	} else {
+	    printf("Another %s is already running, pid=%u\n", name, oldpid);
+	    unlink(tempfile);
+	    free(tempfile);
+	    free(lockfile);
+	    return 1;
+	}
+    }
+}
+
+
+
+void ulockprog(char *name)
+{
+    char	    *lockfile;
+    pid_t	    oldpid;
+    FILE	    *fp;
+
+    lockfile = calloc(PATH_MAX, sizeof(char));
+    snprintf(lockfile, PATH_MAX, "/var/run/%s.pid", name);
+
+    if ((fp = fopen(lockfile, "r")) == NULL) {
+	syslog(LOG_NOTICE, "Can't open lockfile \"%s\"", lockfile);
+	free(lockfile);
+	return;
+    }
+
+    if (fscanf(fp, "%u", &oldpid) != 1) {
+	syslog(LOG_NOTICE, "Can't read old pid from \"%s\"", lockfile);
+	fclose(fp);
+	unlink(lockfile);
+	free(lockfile);
+	return;
+    }
+
+    fclose(fp);
+
+    if (oldpid == getpid()) {
+	(void)unlink(lockfile);
+    }
+
+    free(lockfile);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/logger.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * 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"
+
+
+void logger(char *filename, char *progname, char *data)
+{
+    struct timeval	now;
+    struct tm		ptm;
+    char		*outstr = NULL, *name = NULL;
+    FILE		*logfile;
+
+    name = xstrcpy((char *)"/var/local/log/");
+    name = xstrcat(name, progname);
+    name = xstrcat(name, (char *)"/");
+    name = xstrcat(name, filename);
+
+    gettimeofday(&now, NULL);
+    localtime_r(&now.tv_sec, &ptm);
+
+    if ((logfile = fopen(name, "a+"))) {
+	outstr = calloc(10240, sizeof(char));
+	snprintf(outstr, 10239, "%04d-%02d-%02d %02d:%02d,%s\n", ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, data);
+	fprintf(logfile, outstr);
+	fclose(logfile);
+	free(outstr);
+	outstr = NULL;
+    } else {
+	    syslog(LOG_NOTICE, "logger: cannot open %s for writing", name);
+    }
+
+    free(name);
+    name = NULL;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/rc-switch.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,955 @@
+/*****************************************************************************
+ * Copyright (C) 2014
+ *   
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of the mbsePi-apps
+ *
+ * Based on the Arduino libary for remote control outlet switches.
+ * Project home: http://code.google.com/p/rc-switch/
+ *
+ * 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"
+
+#ifdef HAVE_WIRINGPI_H
+
+
+#define	TYPE_UNDEF	0
+#define	TYPE_MINIMUM	0
+#define	TYPE_A		1
+#define	TYPE_B		2
+#define	TYPE_C		3
+#define	TYPE_D		4
+#define	TYPE_E		3  // TODO: Which Protocol does REV use?
+#define	TYPE_MAXIMUM	4
+
+// Number of maximum High/Low changes per packet.
+// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
+#define RCSWITCH_MAX_CHANGES 67
+
+// i.e. ProtocolCount + 1 (for TYPE_UNDEF)
+#define MAX_PROTOCOLS                   5
+
+#define PROTOCOL_A_SYNC_FACTOR         31
+#define PROTOCOL_A_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_A_ZERO_SECOND_CYCLES   3
+#define PROTOCOL_A_ONE_FIRST_CYCLES     3
+#define PROTOCOL_A_ONE_SECOND_CYCLES    1
+#define PROTOCOL_A_HIGH_FIRST        true
+
+#define PROTOCOL_B_SYNC_FACTOR         10
+#define PROTOCOL_B_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_B_ZERO_SECOND_CYCLES   2
+#define PROTOCOL_B_ONE_FIRST_CYCLES     2
+#define PROTOCOL_B_ONE_SECOND_CYCLES    1
+#define PROTOCOL_B_HIGH_FIRST        true
+
+#define PROTOCOL_C_SYNC_FACTOR         71
+#define PROTOCOL_C_ZERO_FIRST_CYCLES    4
+#define PROTOCOL_C_ZERO_SECOND_CYCLES  11
+#define PROTOCOL_C_ONE_FIRST_CYCLES     9
+#define PROTOCOL_C_ONE_SECOND_CYCLES    6
+#define PROTOCOL_C_HIGH_FIRST        true
+
+// I think, this will work for receive, however, I haven't tested, as I don't own a receiver...
+// As Type D doesn't sync acc. to https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
+// the sync factor is totally undetermined.
+// Malte Diers, 22.11.2013
+#define PROTOCOL_D_SYNC_FACTOR          1
+#define PROTOCOL_D_ZERO_FIRST_CYCLES    1
+#define PROTOCOL_D_ZERO_SECOND_CYCLES   2
+#define PROTOCOL_D_ONE_FIRST_CYCLES     2
+#define PROTOCOL_D_ONE_SECOND_CYCLES    1
+#define PROTOCOL_D_HIGH_FIRST       false
+
+
+#define PROTOCOL3_SYNC_FACTOR   71
+#define PROTOCOL3_0_HIGH_CYCLES  4
+#define PROTOCOL3_0_LOW_CYCLES  11
+#define PROTOCOL3_1_HIGH_CYCLES  9
+#define PROTOCOL3_1_LOW_CYCLES   6
+
+
+
+unsigned long	rcReceivedValue = 0;
+unsigned int	rcReceivedBitlength = 0;
+unsigned int	rcReceivedDelay = 0;
+unsigned int	rcReceivedProtocol = 0;
+int		rcReceiveTolerance = 60;
+int		rcReceiverInterruptPin = -1;
+
+unsigned int	timings[RCSWITCH_MAX_CHANGES];
+int		rcTransmitterPin = -1;
+int		rcPulseLength = 350;	// thermometers 2.4 msec = 2400
+int		rcRepeatTransmit = 10;
+int		rcProtocol = 1;
+
+int		backupProtocol;
+int		backupPulseLength;
+int		backupRepeatTransmit;
+
+
+//const char TYPE_A_CODE[ 6][6]  = { "00000", "10000", "01000", "00100", "00010", "00001"};
+const char TYPE_B_CODE[ 5][5]  = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
+const char TYPE_C_CODE[16][5]  = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0",
+				   "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
+const char TYPE_D_CODE[5][2][9] = { { "11100001", "11110000" }, { "00000000", "00010001" }, { "10000010", "10010011" },
+				    { "11000011", "11010010" }, { "01000001", "01010000" } };
+					/* Type A            Type D */
+const int  PULSE_LENGTH[MAX_PROTOCOLS] 		= { 0, 350, 650, 100, 666, };
+const int  REPEAT_TRANSMIT[MAX_PROTOCOLS] 	= { 0, 10, 10, 10, 4, };
+const int  SYNC_FACTOR[MAX_PROTOCOLS]		= { 0, PROTOCOL_A_SYNC_FACTOR, PROTOCOL_B_SYNC_FACTOR, PROTOCOL_C_SYNC_FACTOR, PROTOCOL_D_SYNC_FACTOR, };
+const int  ZERO_FIRST_CYCLES[MAX_PROTOCOLS]	= { 0, PROTOCOL_A_ZERO_FIRST_CYCLES, PROTOCOL_B_ZERO_FIRST_CYCLES, PROTOCOL_C_ZERO_FIRST_CYCLES, PROTOCOL_D_ZERO_FIRST_CYCLES, };
+const int  ZERO_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_SECOND_CYCLES, PROTOCOL_B_ZERO_SECOND_CYCLES, PROTOCOL_C_ZERO_SECOND_CYCLES, PROTOCOL_D_ZERO_SECOND_CYCLES, };
+const int  ONE_FIRST_CYCLES[MAX_PROTOCOLS]  = { 0, PROTOCOL_A_ONE_FIRST_CYCLES, PROTOCOL_B_ONE_FIRST_CYCLES, PROTOCOL_C_ONE_FIRST_CYCLES, PROTOCOL_D_ONE_FIRST_CYCLES, };
+const int  ONE_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_SECOND_CYCLES, PROTOCOL_B_ONE_SECOND_CYCLES, PROTOCOL_C_ONE_SECOND_CYCLES, PROTOCOL_D_ONE_SECOND_CYCLES, };
+const bool HIGH_FIRST[MAX_PROTOCOLS]        = { 0, PROTOCOL_A_HIGH_FIRST, PROTOCOL_B_HIGH_FIRST, PROTOCOL_C_HIGH_FIRST, PROTOCOL_D_HIGH_FIRST, };
+
+
+char *getCodeWordA(char*, char*, bool);
+char *getCodeWordB(int, int, bool);
+char *getCodeWordC(char, int, int, bool);
+
+char *getCodeWordE(char, int, bool);
+void sendTriState(char*);
+void transmit(int, int, bool);
+void send0(void);
+void send1(void);
+void sendT0(void);
+void sendT1(void);
+void sendTF(void);
+void sendSync(void);
+bool receiveProtocol(int, unsigned int);
+void handleInterrupt(void);
+char *dec2binWcharfill(unsigned long, unsigned int, char);
+
+void setReceiveTolerance(int);
+void setProtocol(int);
+
+void saveProtocol(int);
+void loadProtocol(void);
+
+
+
+/*
+ * Sets the protocol to send.
+ */
+void setProtocol(int nProtocol) {
+
+    if ((nProtocol < TYPE_MINIMUM) || (nProtocol > TYPE_MAXIMUM)) {
+	return;
+    }
+
+    rcProtocol = nProtocol;
+    rcPulseLength = PULSE_LENGTH[nProtocol];
+    rcRepeatTransmit = REPEAT_TRANSMIT[nProtocol];
+}
+
+
+
+/*
+ * Set Receiving Tolerance
+ */
+void setReceiveTolerance(int nPercent) {
+    rcReceiveTolerance = nPercent;
+}
+
+
+
+/*
+ * Enable transmissions
+ *
+ * @param nTransmitterPin    Pin to which the sender is connected to
+ */
+void enableTransmit(int nTransmitterPin) {
+    rcTransmitterPin = nTransmitterPin;
+    pinMode(rcTransmitterPin, OUTPUT);
+}
+
+
+
+/*
+ * Disable transmissions
+ */
+void disableTransmit(void) {
+    rcTransmitterPin = -1;
+}
+
+
+
+/*
+ * Toggle switch, a command looks like B,3,2,1 which means switch type B,
+ * group 3, device 2, status on.
+ */
+int toggleSwitch(char *command)
+{
+    static char	*cmd = NULL;
+    char    *s, cType;
+    int	    rc, iGroup, iDevice, iState;
+
+    cmd = xstrcpy(command);
+    s = strtok(cmd, ",\0");
+    cType = s[0];
+
+    if (cType == 'A') {
+
+    } else if (cType == 'B') {
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iGroup);
+	if (rc != 1)
+	    return 1;
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iDevice);
+	if (rc != 1)
+	    return 1;
+	s = strtok(NULL, ",\0");
+	rc = sscanf(s, "%d", &iState);
+	if (rc != 1)
+	    return 1;
+	free(cmd);
+	return toggleTypeB(iGroup, iDevice, iState);
+    }
+
+    free(cmd);
+    return 1;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type E REV)
+ *
+ * @param sGroup   Code of the switch group (A,B,C,D)
+ * @param nDevice  Number of the switch itself (1..3)
+ * @param bStatus  Status to toggle to
+ */
+int toggleTypeE(char sGroup, int nDevice, bool bStatus) {
+    sendTriState( getCodeWordE(sGroup, nDevice, bStatus) );
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type C Intertechno)
+ *
+ * @param sFamily  Familycode (a..f)
+ * @param nGroup   Number of group (1..4)
+ * @param nDevice  Number of device (1..4)
+ * @param bStatus  Status to toggle to
+ */
+int toggleTypeC(char sFamily, int nGroup, int nDevice, bool bStatus) {
+    char *str = xstrcpy(getCodeWordC(sFamily, nGroup, nDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);	// ???
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on/off (Type B with two rotary/sliding switches)
+ *
+ * @param iGroup    Number of the switch group (1..4)
+ * @param iDevice   Number of the switch itself (1..4)
+ * @param bStatus   Status to toggle to
+ */
+int toggleTypeB(int iGroup, int iDevice, bool bStatus)
+{
+    char  *str = xstrcpy(getCodeWordB(iGroup, iDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);	// They do better with protocol A timings.
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
+ *
+ * @param sGroup    Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
+ * @param sDevice   Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
+ * @param bStatus   Status to toggle to
+ */
+int toggleTypeA(char* sGroup, char* sDevice, bool bStatus) {
+    char *str = xstrcpy(getCodeWordA(sGroup, sDevice, bStatus));
+
+    if (strlen(str) == 0)
+	return 1;
+
+    saveProtocol(TYPE_A);
+    sendTriState( str );
+    loadProtocol();
+    free(str);
+    return 0;
+}
+
+
+
+/*
+ * Returns a char[13], representing the Code Word to be send.
+ * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
+ * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
+ *
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
+ * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ *
+ * @param nAddressCode  Number of the switch group (1..4)
+ * @param nChannelCode  Number of the switch itself (1..4)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+char *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus)
+{
+    int		i, nReturnPos = 0;
+    static char sReturn[13];
+   
+    if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
+    	return '\0';
+    }
+    for (i = 0; i<4; i++) {
+	sReturn[nReturnPos++] = TYPE_B_CODE[nAddressCode][i];
+    }
+
+    for (i = 0; i<4; i++) {
+	sReturn[nReturnPos++] = TYPE_B_CODE[nChannelCode][i];
+    }
+   
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
+    sReturn[nReturnPos] = '\0';
+
+    return sReturn;
+}
+
+
+
+/*
+ * Returns a char[13], representing the Code Word to be send.
+ *
+ * getCodeWordA(char*, char*)
+ *
+ */
+char *getCodeWordA(char* sGroup, char* sDevice, bool bOn)
+{
+    static char sDipSwitches[13];
+    int		i, j = 0;
+
+    for (i=0; i < 5; i++) {
+	sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0';
+    }
+  
+    for (i=0; i < 5; i++) {
+	sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0';
+    }
+
+    if ( bOn ) {
+        sDipSwitches[j++] = '0';
+        sDipSwitches[j++] = 'F';
+    } else {
+        sDipSwitches[j++] = 'F';
+        sDipSwitches[j++] = '0';
+    }
+
+    sDipSwitches[j] = '\0';
+    return sDipSwitches;
+}
+
+
+
+/*
+ * Like getCodeWord (Type C = Intertechno)
+ */
+char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus)
+{
+    static char sReturn[13];
+    int		i, nReturnPos = 0;
+ 
+    if (sFamily < 'a') {
+	// To also enable capital 'A' to 'F'
+	sFamily += 32;
+    }
+
+    if ( sFamily < 'a' || sFamily > 'f' || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
+    	return '\0';
+    }
+  
+    for (i = 0; i<4; i++) {
+    	sReturn[nReturnPos++] = TYPE_C_CODE[ sFamily - 'a' ][i];
+    }
+
+    char *sDeviceGroupCode = dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
+    for (i = 0; i<4; i++) {
+    	sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
+    }
+
+    sReturn[nReturnPos++] = '0';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = 'F';
+    sReturn[nReturnPos++] = bStatus ? 'F' : '0';
+    sReturn[nReturnPos] = '\0';
+
+    return sReturn;
+}
+
+
+
+/*
+ * Decoding for the Quigg Switch Type
+ *
+ * Returns a char[22], representing the States to be send.
+ * A Code Word consists of 1 start bit, 12 address bits and 8 command data bits.
+ * A Code Bit can have 2 different states: "0" (low), "1" (high)
+ *
+ * +--------------+--------------------------------+------------------------------+
+ * | 1 bits start | 12 bits address (device group) | 8 bits (command/switch data) |
+ * |        1     |           110011001100         |             00010001         |
+ * +--------------+--------------------------------+------------------------------+
+ *
+ * Source: https://github.com/d-a-n/433-codes/blob/master/database.md#quigg
+ *
+ * @param sGroup        12-bit Binary ID of the Device Group
+ * @param nDevice       Number of the switch itself (1..4, or 0 to switch the entire Group)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[22]
+ */
+char *getCodeWordD(char *sGroup, int nDevice, bool bStatus)
+{
+    static char sReturn[22];
+    int		i, nReturnPos = 0;
+
+    /* Startbit */
+    sReturn[nReturnPos++] = '1';
+
+    /* 12 bit Group */
+    for (i = 0; i < 12; ++i) {
+	sReturn[nReturnPos++] = sGroup[i];
+    }
+
+    /* 8 Bit Device Identifier + Status (undividable!) */
+    for (i = 0; i < 8; ++i) {
+	sReturn[nReturnPos++] = TYPE_D_CODE[nDevice][bStatus][i];
+    }
+    sReturn[nReturnPos] = 0;
+
+    return sReturn;
+}
+
+
+
+/*
+ * Decoding for the REV Switch Type
+ *
+ * Returns a char[13], representing the Tristate to be send.
+ * A Code Word consists of 7 address bits and 5 command data bits.
+ * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
+ *
+ * +-------------------------------+--------------------------------+-----------------------+
+ * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
+ * | A=1FFF B=F1FF C=FF1F D=FFF1   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | on=00010 off=00001    |
+ * +-------------------------------+--------------------------------+-----------------------+
+ *
+ * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
+ *
+ * @param sGroup        Name of the switch group (A..D, resp. a..d) 
+ * @param nDevice       Number of the switch itself (1..3)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+char *getCodeWordE(char sGroup, int nDevice, bool bStatus){
+    static char sReturn[13];
+    int		i, nReturnPos = 0;
+
+    // Building 4 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sGroupCode;
+    switch(sGroup){
+        case 'a':
+        case 'A':
+            sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
+        case 'b':
+        case 'B':
+            sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
+        case 'c':
+        case 'C':
+            sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
+        case 'd':
+        case 'D':
+            sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
+        default:
+            return '\0';
+    }
+    
+    for (i = 0; i<4; i++) {
+        sReturn[nReturnPos++] = sGroupCode[i];
+    }
+
+
+    // Building 3 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sDevice;
+    switch(nDevice) {
+        case 1:
+            sDevice = dec2binWcharfill(4, 3, 'F'); break;
+        case 2:
+            sDevice = dec2binWcharfill(2, 3, 'F'); break;
+        case 3:
+            sDevice = dec2binWcharfill(1, 3, 'F'); break;
+        default:
+            return '\0';
+    }
+
+    for (i = 0; i<3; i++)
+        sReturn[nReturnPos++] = sDevice[i];
+
+    // fill up rest with zeros
+    for (i = 0; i<5; i++)
+        sReturn[nReturnPos++] = '0';
+
+    // encode on or off
+    if (bStatus)
+        sReturn[10] = '1';
+    else
+        sReturn[11] = '1';
+
+    // last position terminate string
+    sReturn[12] = '\0';
+    return sReturn;
+
+}
+
+
+
+/*
+ * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
+ */
+void sendTriState(char* sCodeWord) {
+    int nRepeat;
+
+    for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) {
+	int i = 0;
+	while (sCodeWord[i] != '\0') {
+	    switch(sCodeWord[i]) {
+		case '0':
+			    sendT0();
+			    break;
+		case 'F':
+			    sendTF();
+			    break;
+		case '1':
+			    sendT1();
+			    break;
+	    }
+	    i++;
+	}
+	sendSync();    
+    }
+}
+
+
+
+/*
+void RCSwitch::send(unsigned long Code, unsigned int length) {
+  this->send( this->dec2binWzerofill(Code, length) );
+}
+
+void RCSwitch::send(char* sCodeWord) {
+  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
+    int i = 0;
+    while (sCodeWord[i] != '\0') {
+      switch(sCodeWord[i]) {
+        case '0':
+          this->send0();
+        break;
+        case '1':
+          this->send1();
+        break;
+      }
+      i++;
+    }
+    this->sendSync();
+  }
+}
+*/
+
+
+void transmit(int nFirstPulses, int nSecondPulses, bool bHighFirst)
+{
+    bool	disabled_Receive = false;
+    int		nReceiverInterrupt_backup = rcReceiverInterruptPin;
+    
+    if (rcTransmitterPin != -1) {
+        if (rcReceiverInterruptPin != -1) {
+            disableReceive();
+            disabled_Receive = true;
+        }
+        digitalWrite(rcTransmitterPin, bHighFirst ? HIGH : LOW);
+	delayMicroseconds( rcPulseLength * nFirstPulses);
+        digitalWrite(rcTransmitterPin, bHighFirst ? LOW : HIGH);
+	delayMicroseconds( rcPulseLength * nSecondPulses);
+        
+        if (disabled_Receive) {
+            enableReceiveIRQ(nReceiverInterrupt_backup);
+        }
+    }
+}
+
+
+
+/*
+ * Sends a "0" Bit
+ *                       _    
+ * Waveform Protocol 1: | |___
+ *                       _  
+ * Waveform Protocol 2: | |__
+ *                       ____
+ * Waveform Protocol 3: |    |___________
+ */
+//void send0(void) {
+//	if (rcProtocol == 1){
+//		transmit(1,3);
+//	}
+//	else if (rcProtocol == 2) {
+//		transmit(1,2);
+//	}
+//    else if (rcProtocol == 3) {
+//        transmit(4,11);
+//    }
+//}
+
+
+
+/*
+ * Sends a "1" Bit
+ *                       ___  
+ * Waveform Protocol 1: |   |_
+ *                       __  
+ * Waveform Protocol 2: |  |_
+ *                       _________
+ * Waveform Protocol 3: |         |______
+ */
+//void send1(void) {
+//  	if (rcProtocol == 1){
+//		transmit(3,1);
+//	}
+//	else if (rcProtocol == 2) {
+//		transmit(2,1);
+//	}
+//    else if (rcProtocol == 3) {
+//        transmit(9,6);
+//    }
+//}
+
+
+
+/*
+ * Sends a Tri-State "0" Bit
+ *            _     _
+ * Waveform: | |___| |___
+ */
+void sendT0(void) {
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(1,3,true);
+//    transmit(1,3,true);
+}
+
+
+
+/*
+ * Sends a Tri-State "1" Bit
+ *            ___   ___
+ * Waveform: |   |_|   |_
+ */
+void sendT1(void) {
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(3,1,true);
+//    transmit(3,1,true);
+}
+
+
+
+/*
+ * Sends a Tri-State "F" Bit
+ *            _     ___
+ * Waveform: | |___|   |_
+ */
+void sendTF(void) {
+    transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);   
+    transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]);
+//    transmit(1,3,true);
+//    transmit(3,1,true);
+}
+
+
+
+/*
+ * Sends a "Sync" Bit
+ *                       _
+ * Waveform Protocol 1: | |_______________________________
+ *                       _
+ * Waveform Protocol 2: | |__________
+ *                       ____
+ * Waveform Protocol 3: |    |_______________________________________________________________________
+ *
+ * Waveform Protocol D: (none, just pause 80 msecs)
+ */
+void sendSync(void) {
+
+    if (rcProtocol == TYPE_A) {
+	transmit(1,31,true);
+    } else if (rcProtocol == TYPE_B) {
+	transmit(1,10,true);
+    } else if (rcProtocol == TYPE_C) {
+        transmit(4,71,true);
+    } else if (rcProtocol == TYPE_D) {
+	transmit(0,1,false);
+	delayMicroseconds(80000);
+    }
+}
+
+
+
+/*
+ * Enable receiving data
+ */
+void enableReceiveIRQ(int Pin) {
+    rcReceiverInterruptPin = Pin;
+    enableReceive();
+}
+
+void enableReceive(void) {
+    if (rcReceiverInterruptPin != -1) {
+	rcReceivedValue = 0;
+	rcReceivedBitlength = 0;
+	wiringPiISR(rcReceiverInterruptPin, INT_EDGE_BOTH, &handleInterrupt);
+    }
+}
+
+
+
+/*
+ * Disable receiving data
+ */
+void disableReceive() {
+    // wiringPi disable interrupts ???
+    rcReceiverInterruptPin = -1;
+}
+
+
+
+bool available(void) {
+    return rcReceivedValue != 0;
+}
+
+
+
+void resetAvailable(void) {
+    rcReceivedValue = 0;
+}
+
+
+
+unsigned long getReceivedValue(void) {
+    return rcReceivedValue;
+}
+
+
+
+unsigned int getReceivedBitlength(void) {
+    return rcReceivedBitlength;
+}
+
+
+
+unsigned int getReceivedDelay(void) {
+    return rcReceivedDelay;
+}
+
+
+
+unsigned int getReceivedProtocol(void) {
+    return rcReceivedProtocol;
+}
+
+
+
+unsigned int* getReceivedRawdata(void) {
+    return timings;
+}
+
+
+
+/*
+ * ASK protool 1
+ */
+bool receiveProtocol(int prot, unsigned int changeCount)
+{
+    unsigned long	code = 0;
+    unsigned long	ldelay = timings[0] / SYNC_FACTOR[prot];
+    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
+    int			i;
+
+    if (prot < TYPE_MINIMUM || prot > TYPE_MAXIMUM) {
+	return false;
+    }
+
+    for (i = 1; i<changeCount ; i=i+2) {
+      
+	if (timings[i]   > ldelay * ZERO_FIRST_CYCLES[prot]  - delayTolerance && 
+	    timings[i]   < ldelay * ZERO_FIRST_CYCLES[prot]  + delayTolerance && 
+	    timings[i+1] > ldelay * ZERO_SECOND_CYCLES[prot] - delayTolerance && 
+	    timings[i+1] < ldelay * ZERO_SECOND_CYCLES[prot] + delayTolerance) {
+      	    code = code << 1;
+    	}  else if (timings[i]   > ldelay * ONE_FIRST_CYCLES[prot]  - delayTolerance &&
+		    timings[i]   < ldelay * ONE_FIRST_CYCLES[prot]  + delayTolerance &&
+		    timings[i+1] > ldelay * ONE_SECOND_CYCLES[prot] - delayTolerance &&
+		    timings[i+1] < ldelay * ONE_SECOND_CYCLES[prot] + delayTolerance) {
+	    code+=1;
+	    code = code << 1;
+	} else {
+      	    // Failed
+      	    i = changeCount;
+      	    code = 0;
+    	}
+    }      
+    code = code >> 1;
+    if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
+    	rcReceivedValue = code;
+    	rcReceivedBitlength = changeCount / 2;
+    	rcReceivedDelay = ldelay;
+    	rcReceivedProtocol = prot;
+    }
+
+    return (code != 0);
+}
+
+
+
+void handleInterrupt() {
+
+  static unsigned int duration;
+  static unsigned int changeCount;
+  static unsigned long lastTime;
+  static unsigned int repeatCount;
+
+ 
+  long thistime = micros();
+  duration = thistime - lastTime;
+
+  if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) {    
+    repeatCount++;
+    changeCount--;
+    if (repeatCount == 2) {
+      if (receiveProtocol(TYPE_A, changeCount) == false) {
+        if (receiveProtocol(TYPE_B, changeCount) == false) {
+	  if (receiveProtocol(TYPE_C, changeCount) == false) {
+	    if (receiveProtocol(TYPE_D, changeCount) == false) {
+              //failed
+	    }
+	  }
+        }
+      }
+      repeatCount = 0;
+    }
+    changeCount = 0;
+  } else if (duration > 5000) {
+    changeCount = 0;
+  }
+
+  if (changeCount >= RCSWITCH_MAX_CHANGES) {
+    changeCount = 0;
+    repeatCount = 0;
+  }
+  timings[changeCount++] = duration;
+  lastTime = thistime;  
+}
+
+
+
+/*
+ * Turns a decimal value to its binary representation
+ */
+char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength)
+{
+    return dec2binWcharfill(Dec, bitLength, '0');
+}
+
+char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill)
+{
+    static char		bin[64];
+    unsigned int	i = 0, j;
+
+    while (Dec > 0) {
+    	bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
+    	Dec = Dec >> 1;
+    }
+
+    for (j = 0; j< bitLength; j++) {
+    	if (j >= bitLength - i) {
+      	    bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
+    	} else {
+      	    bin[j] = fill;
+    	}
+    }
+    bin[bitLength] = '\0';
+  
+    return bin;
+}
+
+
+void saveProtocol(int prot)
+{
+    backupProtocol = rcProtocol;
+    backupPulseLength = rcPulseLength;
+    backupRepeatTransmit = rcRepeatTransmit;
+
+    setProtocol(prot);
+}
+
+
+
+void loadProtocol(void)
+{
+    rcProtocol = backupProtocol;
+    rcPulseLength = backupPulseLength;
+    rcRepeatTransmit = backupRepeatTransmit;
+}
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/rdconfig.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,350 @@
+/*****************************************************************************
+ * 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"
+
+
+bool		debug = FALSE;
+static char	*mypath;
+static char	*k, *v;
+static int	linecnt = 0;
+sys_config	Config;			/* System configuration		*/
+
+
+
+static int getstr(char **);
+static int getint(char **);
+static int getw1(char **);
+#ifdef HAVE_WIRINGPI_H
+static int getrcs(char **);
+#endif
+//static int getbyt(char **);
+//static int gethex(char **);
+
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+
+/*
+ * System configuration table
+ */
+key_list keytab[] = {
+    {(char *)"mosq_host",	getstr,		&Config.mosq_host},
+    {(char *)"mosq_port",	getint,		(char **)&Config.mosq_port},
+    {(char *)"w1therm",		getw1,		(char **)&Config.w1therms},
+#ifdef HAVE_WIRINGPI_H
+    {(char *)"lcd_cols",	getint,		(char **)&Config.lcd_cols},
+    {(char *)"lcd_rows",	getint,		(char **)&Config.lcd_rows},
+    {(char *)"rx433",		getint,		(char **)&Config.rx433},
+    {(char *)"tx433",		getint,		(char **)&Config.tx433},
+    {(char *)"rcswitch",	getrcs,		(char **)&Config.rcswitch},
+#endif
+    {NULL,			NULL,		NULL}
+};
+
+
+
+void killconfig(void)
+{
+    w1_therm	*tmp1, *old1;
+#ifdef HAVE_WIRINGPI_H
+    rc_switch	*tmp2, *old2;
+#endif
+
+    if (Config.name)
+	free(Config.name);
+    Config.name = NULL;
+
+    if (Config.mosq_host)
+	free(Config.mosq_host);
+    Config.mosq_host= (char *)"localhost";
+    Config.mosq_port = 1883;
+
+    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
+	old1 = tmp1->next;
+	if (tmp1->master)
+	    free(tmp1->master);
+	if (tmp1->name)
+	    free(tmp1->name);
+	if (tmp1->alias)
+	    free(tmp1->alias);
+	free(tmp1);
+    }
+    Config.w1therms = NULL;
+    Config.my_port = 6554;
+
+#ifdef HAVE_WIRINGPI_H
+    Config.lcd_cols = 16;
+    Config.lcd_rows = 2;
+    Config.rx433 = -1;
+    Config.tx433 = -1;
+
+    for (tmp2 = Config.rcswitch; tmp2; tmp2 = old2) {
+	old2 = tmp2->next;
+	if (tmp2->address)
+	    free(tmp2->address);
+	tmp2->address = NULL;
+	if (tmp2->alias)
+	    free(tmp2->alias);
+	tmp2->alias = NULL;
+	free(tmp2);
+    }
+    Config.rcswitch = NULL;
+
+#endif
+}
+
+
+
+int rdconfig(char *config) 
+{
+    char	buf[256], *p;
+    FILE	*fp;
+    int		i, rc = 0;
+
+    killconfig();
+
+    /*
+     * Search config file
+     */
+    mypath = xstrcpy(getenv((char *)"HOME"));
+    mypath = xstrcat(mypath, (char *)"/mbsepi-apps/");
+    mypath = xstrcat(mypath, config);
+    if ((fp = fopen(mypath, "r")) == NULL) {
+	/*
+	 * Not in the users home directory
+	 */
+	free(mypath);
+	mypath = xstrcpy((char *)"/etc/mbsepi-apps/");
+	mypath = xstrcat(mypath, config);
+	if ((fp = fopen(mypath, "r")) == NULL) {
+	    /*
+	     * Try /usr/local/etc
+	     */
+	    free(mypath);
+	    mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/");
+	    mypath = xstrcat(mypath, config);
+	    if ((fp = fopen(mypath, "r")) == NULL) {
+		syslog(LOG_NOTICE, "rdconfig: could not open %s", mypath);
+		return 1;
+	    }
+	}
+    }
+
+    linecnt = 0;
+    while (fgets(buf, sizeof(buf) -1, fp)) {
+	linecnt++;
+	if (*(p = buf + strlen(buf) -1) != '\n') {
+	    syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf);
+	    rc = 1;
+	    break;
+	}
+	*p-- = '\0';
+	while ((p >= buf) && isspace(*p))
+	    *p-- = '\0';
+	k = buf;
+	while (*k && isspace(*k))
+	    k++;
+	p = k;
+	while (*p && !isspace(*p))
+	    p++;
+	*p++='\0';
+	v = p;
+	while (*v && isspace(*v)) 
+	    v++;
+
+	if ((*k == '\0') || (*k == '#')) {
+	    continue;
+	}
+
+	for (i = 0; keytab[i].key; i++)
+	    if (strcasecmp(k,keytab[i].key) == 0)
+		break;
+
+	if (keytab[i].key == NULL) {
+	    syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - unknown keyword", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+	    rc = 1;
+	    break;
+	} else if ((keytab[i].prc(keytab[i].dest))) {
+	    rc = 1;
+	    break;
+	}
+
+    }
+    fclose(fp);
+
+    free(mypath);
+    mypath = NULL;
+
+    return rc;
+}
+
+
+
+static int getstr(char **dest)
+{
+    if (debug)
+	syslog(LOG_NOTICE, "rdconfig: getstr: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+
+    *dest = xstrcpy(v);
+    return 0;
+}
+
+
+
+static int getint(char **dest)
+{
+    if (debug)
+	syslog(LOG_NOTICE, "rdconfig: getint: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+
+    if (strspn(v,"0123456789") != strlen(v)) 
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad numeric", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+    else 
+	*((int*)dest)=atoi(v);
+    return 0;
+}
+
+
+
+static int getw1(char **dest)
+{
+    char	*p, *q = NULL, *r = NULL;
+    w1_therm	**tmpm;
+    int		rc = 0, tmpp;
+
+    for (p = v; *p && !isspace(*p); p++);
+    if (*p)
+	*p++ = '\0';
+    while (*p && isspace(*p))
+	p++;
+    if (*p == '\0') {
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
+	return 1;
+    }
+
+    for (q = p; *q && !isspace(*q); q++);
+    if (*q && isspace(*q)) {
+	if (*q)
+	    *q++ = '\0';
+	while (*q && isspace(*q))
+	    q++;
+
+	for (r = q; *r && !isspace(*r); r++);
+	if (*r)
+	    *r++ = '\0';
+	rc = sscanf(p, "%d", &tmpp);
+	if (rc != 1) {
+	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s is not a integer value", mypath, linecnt, p);
+	    return 1;
+	}
+	if (debug)
+	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s %d %s %s", mypath, linecnt, v, tmpp, q, r);
+    }
+
+    for (tmpm = (w1_therm**)dest; *tmpm; tmpm=&((*tmpm)->next));
+    (*tmpm) = (w1_therm *) xmalloc(sizeof(w1_therm));
+    (*tmpm)->next = NULL;
+    (*tmpm)->master = xstrcpy(v);
+    (*tmpm)->bus = tmpp;
+    (*tmpm)->name = xstrcpy(q);
+    (*tmpm)->alias = xstrcpy(r);
+    (*tmpm)->present = 0;
+    (*tmpm)->lastval = 0;
+    (*tmpm)->update = 0;
+
+    return 0;
+}
+
+
+
+#ifdef HAVE_WIRINGPI_H
+static int getrcs(char **dest)
+{
+    char        *p, *q = NULL, *r = NULL;
+    rc_switch   **tmpm;
+
+    for (p = v; *p && !isspace(*p); p++);
+	if (*p)
+	    *p++ = '\0';
+    while (*p && isspace(*p))
+	p++;
+    if (*p == '\0') {
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
+	return 1;
+    }
+
+    for (q = p; *q && !isspace(*q); q++);
+    if (*q && isspace(*q)) {
+	if (*q)
+	    *q++ = '\0';
+	while (*q && isspace(*q))
+	    q++;
+
+	for (r = q; *r && !isspace(*r); r++);
+	if (*r)
+	    *r++ = '\0';
+	if (debug)
+	    syslog(LOG_NOTICE, "rdconfig: getrcs: %s(%d): %s %s", mypath, linecnt, v, p);
+    }
+
+    for (tmpm = (rc_switch**)dest; *tmpm; tmpm=&((*tmpm)->next));
+    (*tmpm) = (rc_switch *) xmalloc(sizeof(rc_switch));
+    (*tmpm)->next = NULL;
+    (*tmpm)->address = xstrcpy(v);
+    (*tmpm)->alias = xstrcpy(p);
+
+    return 0;
+}
+#endif
+
+
+/*
+static int getbyt(char **dest)
+{
+    Log_Msg("[rdconfig] getbyt: %s(%d): %s %s", mypath, linecnt, k, v);
+    if (strspn(v,"0123456789") != strlen(v))
+	Log_Msg("[rdconfig] %s(%d): %s %s - bad numeric", mypath, linecnt, S(k), S(v));
+    else
+	*((Uint8*)dest)=atoi(v);
+    return 0;
+}
+*/
+
+
+/*
+static int gethex(char **dest)
+{
+    unsigned int    val = 0;
+    int		    rc;
+
+    Log_Msg("[rdconfig] gethex: %s(%d): %s %s", mypath, linecnt, k, v);
+    rc = sscanf(v, "%08x", &val);
+    if (rc != 1) {
+	Log_Msg("[rdconfig] %s(%d): %s %s - bad hex value", mypath, linecnt, S(k), S(v));
+	return 1;
+    }
+    *((int*)dest) = val;
+
+    return 0;
+}
+*/
+
+
--- a/thermferm/sensors.c	Sun May 25 16:39:54 2014 +0200
+++ b/thermferm/sensors.c	Sun May 25 22:06:56 2014 +0200
@@ -20,8 +20,7 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
-#include "../lib/mbselib.h"
-#include "sensors.h"
+#include "thermferm.h"
 
 #ifdef HAVE_WIRINGPI_H
 
--- a/thermferm/sensors.h	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#ifndef	MY_SENSORS_H
-#define MY_SENSORS_H
-
-#ifdef HAVE_WIRINGPI_H
-
-PI_THREAD (my_sensors_loop);
-
-#endif
-
-#endif
--- a/thermferm/server.c	Sun May 25 16:39:54 2014 +0200
+++ b/thermferm/server.c	Sun May 25 22:06:56 2014 +0200
@@ -20,9 +20,6 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
-
-#include "../lib/mbselib.h"
-#include "server.h"
 #include "thermferm.h"
 
 extern bool		my_shutdown;
@@ -138,10 +135,10 @@
 	hostname = hp->h_name;
     }
 
-    if (debug) {
-    	syslog(LOG_NOTICE, "Start new client connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
-	fprintf(stdout, "Start new client connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
-    }
+//    if (debug) {
+//    	syslog(LOG_NOTICE, "Start new client connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
+//	fprintf(stdout, "Start new client connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
+//    }
 
     memset((char *)&buf, 0, SS_BUFSIZE);
     fromlen = sizeof(peeraddr_in);
@@ -201,10 +198,17 @@
 		if (debug)
 		    fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
 		if (rc == 1) {
-		    srv_send("ack");
-		    cs_mode = 'b';
-		    cs_beerSet = newtemp;
+		    if ((cc_tempSetMin <= newtemp) && (newtemp <= cc_tempSetMax)) {
+		    	syslog(LOG_NOTICE, "Beer temperature set to %.1f degrees in web interface", newtemp);
+		    	srv_send("ack");
+		    	cs_mode = 'b';
+		    	cs_beerSet = newtemp;
+		    } else {
+			syslog(LOG_NOTICE, "Beer temperature setting %.1f is outside of allowed range %.1f - %.1f", newtemp, cc_tempSetMin, cc_tempSetMax);
+			srv_send("err");
+		    }
 		} else {
+		    syslog(LOG_NOTICE, "Cannot convert temperature '%s' to float", inp);
 		    srv_send("err");
 		}
 		free(inp);
@@ -214,18 +218,45 @@
 		if (debug)
 		    fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
 		if (rc == 1) {
-		    srv_send("ack");
-		    cs_mode = 'f';
-		    cs_fridgeSet = newtemp;
+		    if ((cc_tempSetMin <= newtemp) && (newtemp <= cc_tempSetMax)) {
+			syslog(LOG_NOTICE, "Fridge temperature set to %.1f degrees in web interface", newtemp);
+		    	srv_send("ack");
+		    	cs_mode = 'f';
+		    	cs_fridgeSet = newtemp;
+		    } else {
+			syslog(LOG_NOTICE, "Fridge temperature setting %.1f is outside of allowed range %.1f - %.1f", newtemp, cc_tempSetMin, cc_tempSetMax);
+			srv_send("err");
+		    }
 		} else {
+		    syslog(LOG_NOTICE, "Cannot convert temperature '%s' to float", inp);
 		    srv_send("err");
 		}
 		free(inp);
 	    } else if (strncmp(buf, "setOff", 6) == 0) {
 		if (debug)
 		    fprintf(stdout, "temperature control disabled\n");
+		syslog(LOG_NOTICE, "Notification: Temperature control disabled");
 		cs_mode = 'o';
 		srv_send("ack");
+	    } else if (strncmp(buf, "setParameters", 13) == 0) {
+		if (debug)
+		    fprintf(stdout, "FIXME:\n");
+		srv_send("ack");
+	// stopScript
+	// quit
+	// eraseLogs
+	// interval
+	// startNewBrew
+	// pauseLogging
+	// stopLogging
+	// resumeLogging
+	// dateTimeFormatDisplay
+	    } else if (strncmp(buf, "setActiveProfile", 16) == 0) {
+		syslog(LOG_NOTICE, "Setting profile '%s' as active profile", "undefined");
+	// programArduino
+	// refreshDeviceList
+	// getDeviceList
+	// applyDevice
 	    } else {
 		if (debug)
 		    fprintf(stdout, "unknown command \"%s\"\n", buf);
@@ -234,10 +265,10 @@
 	}
     }
 
-    if (debug) {
-    	syslog(LOG_NOTICE, "End connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
-	fprintf(stdout, "End connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
-    }
+//    if (debug) {
+//    	syslog(LOG_NOTICE, "End connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
+//	fprintf(stdout, "End connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
+//    }
 
     close(s);
 }
--- a/thermferm/server.h	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-#ifndef	MY_SERVER_H
-#define MY_SERVER_H
-
-
-PI_THREAD (my_server_loop);
-
-#endif
--- a/thermferm/thermferm.c	Sun May 25 16:39:54 2014 +0200
+++ b/thermferm/thermferm.c	Sun May 25 22:06:56 2014 +0200
@@ -20,10 +20,7 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
-#include "../lib/mbselib.h"
 #include "thermferm.h"
-#include "sensors.h"
-#include "server.h"
 
 #ifdef HAVE_WIRINGPI_H
 
--- a/thermferm/thermferm.h	Sun May 25 16:39:54 2014 +0200
+++ b/thermferm/thermferm.h	Sun May 25 22:06:56 2014 +0200
@@ -1,10 +1,166 @@
-#ifndef	_MAIN_H
-#define	_MAIN_H
+#ifndef	_MBSELIB_H
+#define	_MBSELIB_H
 
 
 #define TRUE 1
 #define FALSE 0
 
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <getopt.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <poll.h>
+
+
+/* mosquitto */
+#include <mosquitto.h>
+
+#ifdef HAVE_WIRINGPI_H
+/* wiringPi */
+#include <wiringPi.h>
+#include <pcf8574.h>
+#include <lcd.h>
+
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+#define MBSE_SS(x) (x)?(x):"(null)"
+
+/* rdconfig.c */
+typedef struct _key_list {
+    char	*key;
+    int		(*prc)(char **);
+    char	**dest;
+} key_list;
+
+typedef struct _w1_therm {
+    struct _w1_therm    *next;
+    char                *master;                /* Master for this device       */
+    int                 bus;                    /* Reserved for ds2482-800      */
+    char                *name;                  /* Name of this device          */
+    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 {
+    struct _rc_switch	*next;
+    char		*address;		/* Address code			*/
+    char		*alias;			/* Friendly name		*/
+} rc_switch;
+
+typedef struct _sys_config {
+    char		*name;			/* Configuration name		*/
+    char		*mosq_host;		/* mosquitto server hostname	*/
+    int			mosq_port;		/* mosquitto server port	*/
+    int			my_port;		/* my client/server port	*/
+    w1_therm		*w1therms;		/* 1-wire temp sensors		*/
+#ifdef HAVE_WIRINGPI_H
+    int			lcd_cols;		/* LCD display columns		*/
+    int			lcd_rows;		/* LCD display rows		*/
+    int			rx433;			/* 433 MHz receiver pin		*/
+    int			tx433;			/* 433 MHz transmitter pin	*/
+    rc_switch		*rcswitch;		/* 433 MHz RC Power switches	*/
+#endif
+} sys_config;
+
+
+void killconfig(void);
+int  rdconfig(char *);
+
+
+/* lock.c */
+int  lockprog(char *);
+void ulockprog(char *);
+
+
+/* xutil.c */
+char *xmalloc(size_t);
+char *xstrcpy(char *);
+char *xstrcat(char *, char *);
+
+
+#ifdef HAVE_WIRINGPI_H
+
+/* lcd-pcf8574.c */
+// Defines for the pcf8574 Pi LCD interface board
+#define AF_BASE         100
+
+#define AF_RS           (AF_BASE + 0)
+#define AF_RW           (AF_BASE + 1)
+#define AF_E            (AF_BASE + 2)
+#define AF_BACKLIGHT    (AF_BASE + 3)
+#define AF_DB4          (AF_BASE + 4)
+#define AF_DB5          (AF_BASE + 5)
+#define AF_DB6          (AF_BASE + 6)
+#define AF_DB7          (AF_BASE + 7)
+
+void setBacklight (int);
+int  initLCD (int, int);
+void mb_lcdPutchar(const int, unsigned char);
+void mb_lcdPuts(const int, const char *);
+void mb_lcdClear(const int);
+
+
+/* logger.c */
+void logger(char *, char *, char *);
+
+
+/* rc-switch.c */
+int  toggleSwitch(char *);
+int  toggleTypeA(char *, char *, bool);
+int  toggleTypeB(int, int, bool);
+int  toggleTypeC(char, int, int, bool);
+int  toggleTypeE(char, int, bool);
+
+void enableReceiveIRQ(int interrupt);
+void enableReceive(void);
+void disableReceive(void);
+bool available(void);
+void resetAvailable(void);
+
+unsigned long getReceivedValue(void);
+unsigned int getReceivedBitlength(void);
+unsigned int getReceivedDelay(void);
+unsigned int getReceivedProtocol(void);
+unsigned int *getReceivedRawdata(void);
+
+void enableTransmit(int);
+void disableTransmit(void);
+
+char *dec2binWzerofill(unsigned long, unsigned int);
+
+
+/* dht11.c */
+void dht11Read(void);
+void dht11Init(int, int, int);
+
+PI_THREAD (my_sensors_loop);
+PI_THREAD (my_server_loop);
+
+#endif
 
 
 #endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/xutil.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * Copyright (C) 2008-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"
+
+
+char *xmalloc(size_t size)
+{
+    char *tmp;
+
+    tmp = malloc(size);
+    if (!tmp) 
+	abort();
+			            
+    return tmp;
+}
+
+
+
+char *xstrcpy(char *src)
+{
+    char    *tmp;
+
+    if (src == NULL) 
+	return(NULL);
+    tmp = xmalloc(strlen(src)+1);
+    strcpy(tmp, src);
+    return tmp;
+}
+
+
+
+char *xstrcat(char *src, char *add)
+{
+    char    *tmp;
+    size_t  size = 0;
+
+    if ((add == NULL) || (strlen(add) == 0))
+	return src;
+    if (src)
+	size = strlen(src);
+    size += strlen(add);
+    tmp = xmalloc(size + 1);
+    *tmp = '\0';
+    if (src) {
+	strcpy(tmp, src);
+	free(src);
+    }
+    strcat(tmp, add);
+    return tmp;
+}
+
+
--- a/thermometers/Makefile	Sun May 25 16:39:54 2014 +0200
+++ b/thermometers/Makefile	Sun May 25 22:06:56 2014 +0200
@@ -2,10 +2,9 @@
 
 include ../Makefile.global
 
-SRCS		= main.c 
-HDRS		= main.h 
-OBJS		= main.o 
-SLIBS		= ../lib/libmbse.a
+SRCS		= $(wildcard *.c)
+HDRS		= $(wildcard *.h)
+OBJS		= $(SRCS:.c=.o)
 TARGET		= thermometers
 OTHER		= Makefile
 
@@ -16,8 +15,8 @@
 
 all:		${TARGET}
 
-thermometers:	${OBJS} ${SLIBS}
-		${CC} -o thermometers ${OBJS} ${LDFLAGS} ${LIBS} ${SLIBS}
+thermometers:	${OBJS}
+		${CC} -o thermometers ${OBJS} ${LDFLAGS} -lmosquitto ${LIBS}
 
 clean:
 		rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak
@@ -54,5 +53,8 @@
 
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
-main.o: ../lib/mbselib.h main.h
+rdconfig.o: thermometers.h
+xutil.o: thermometers.h
+lcd-pcf8574.o: thermometers.h
+thermometers.o: thermometers.h
 # End of generated dependencies
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermometers/lcd-pcf8574.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,142 @@
+/*
+ * lcd-pcf8574.c:
+ *	Text-based LCD driver library code
+ *	This is designed to drive the HD44780U LCD display connected via
+ *	a "LCM1602 IIC  A0 A1 A2" board with a PCF8574 I2C controller.
+ *
+ * Copyright (c) 2012-2013 Gordon Henderson.
+ * Copyright (c) 2014 Michiel Broek.
+ ***********************************************************************
+ *
+ *    mbsePi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    mbsePi 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 Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public License
+ *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include "thermometers.h"
+
+#ifdef HAVE_WIRINGPI_H
+
+int			lcdHandle;
+unsigned char		lcdbuf[MAX_LCDS][20][4];
+
+struct lcdDataStruct
+{
+    int bits, rows, cols ;
+    int rsPin, strbPin ;
+    int dataPins [8] ;
+    int cx, cy ;
+};
+extern struct lcdDataStruct	*lcds [MAX_LCDS];
+
+
+/*
+ * Some LCD functions are extended shadow copies of the wiringPi functions.
+ * The difference is that the lcdbuf will be updated with the contents on
+ * the hardware display. This copy can then be used for a remote display
+ */
+
+
+/*
+ * setBacklight:
+ *********************************************************************************
+ */
+
+void setBacklight (int value)
+{
+  pinMode (AF_BACKLIGHT, OUTPUT) ;
+  digitalWrite (AF_BACKLIGHT, (value & 1)) ;
+}
+
+
+
+/*
+ * initLCD:
+ *********************************************************************************
+ */
+
+int initLCD (int cols, int rows)
+{
+    int	x, y;
+
+    if (!((rows == 1) || (rows == 2) || (rows == 4))) {
+    	fprintf (stderr, "rows must be 1, 2 or 4\n") ;
+    	return EXIT_FAILURE ;
+    }
+
+    if (!((cols == 16) || (cols == 20))) {
+    	fprintf (stderr, "cols must be 16 or 20\n") ;
+    	return EXIT_FAILURE ;
+    }
+
+    pcf8574Setup(AF_BASE, 0x27) ;
+    pinMode (AF_RW, OUTPUT) ;
+    digitalWrite (AF_RW, LOW) ;        // Not used with wiringPi - always in write mode
+
+    /*
+     * The other control pins are initialised with lcdInit ()
+     */
+    lcdHandle = lcdInit (rows, cols, 4, AF_RS, AF_E, AF_DB4, AF_DB5, AF_DB6, AF_DB7, 0, 0, 0, 0) ;
+    if (lcdHandle < 0) {
+    	fprintf (stderr, "lcdInit failed\n") ;
+    	return -1 ;
+    }
+
+    lcdClear (lcdHandle) ;
+    for (x = 0; x < 20; x++)
+	for (y = 0; y < 4; y++)
+	    lcdbuf[lcdHandle][x][y] = ' ';
+
+    setBacklight (1) ;
+
+    return 0 ;
+}
+
+
+
+void mb_lcdPutchar(const int fd, unsigned char data)
+{
+    struct lcdDataStruct *lcd = lcds[fd];
+
+    /*
+     * Write to our buffer first, then to the wiringPi driver.
+     * Writing to wiringPi updates the cursor position.
+     */
+    lcdbuf[fd][lcd->cx][lcd->cy] = data;
+    lcdPutchar(fd, data);
+}
+
+
+
+void mb_lcdPuts(const int fd, const char *string)
+{
+    while (*string)
+	mb_lcdPutchar (fd, *string++);
+}
+
+
+
+void mb_lcdClear(const int fd)
+{
+    int	x, y;
+
+    lcdClear(fd);
+    for (x = 0; x < 20; x++)
+	for (y = 0; y < 4; y++)
+	    lcdbuf[fd][x][y] = ' ';
+}
+
+
+
+#endif
+
--- a/thermometers/main.c	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,554 +0,0 @@
-/*****************************************************************************
- * 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 "../lib/mbselib.h"
-#include "main.h"
-
-
-#define STATUS_CONNECTING 0
-#define STATUS_CONNACK_RECVD 1
-#define STATUS_WAITING 2
-
-/* Global variables for use in callbacks. */
-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;
-static bool		my_shutdown = false;
-static pid_t		pgrp, mypid;
-
-extern bool		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;
-}
-
-
-
-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 (my_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);
-}
-
-
-
-#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, "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)
-{
-    char                *id = NULL, *state = NULL;
-    struct mosquitto    *mosq = NULL;
-    char                hostname[256], buf[1024];
-    int                 temp, rc, deviation, keepalive = 60;
-#ifdef HAVE_WIRINGPI_H
-    int			lcdupdate;
-#endif
-    unsigned int        max_inflight = 20;
-    char                err[1024];
-    w1_therm		*tmp1, *old1;
-    char		*device, *alias, line[60], *p = NULL;
-    FILE		*fp;
-
-    /*
-     * Initialize mosquitto communication
-     */
-    mosquitto_lib_init();
-
-    /*
-     * Build MQTT id
-     */
-    hostname[0] = '\0';
-    gethostname(hostname, 256);
-    hostname[255] = '\0';
-
-    id = xstrcpy((char *)"thermometers/");
-    id = xstrcat(id, hostname);
-    if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH) {
-	/*
-	 * Enforce maximum client id length of 23 characters
-	 */
-	id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
-    }
-
-    mosq = mosquitto_new(id, true, NULL);
-    if(!mosq) {
-	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(mosq, my_log_callback);
-    }
-
-    /*
-     * Set our will
-     */
-    state = xstrcpy((char *)"clients/");
-    state = xstrcat(state, hostname);
-    state = xstrcat(state, (char *)"/thermometers/state");
-    sprintf(buf, "0");
-    if ((rc = mosquitto_will_set(mosq, 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(mosq, max_inflight);
-    mosquitto_connect_callback_set(mosq, my_connect_callback);
-    mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
-    mosquitto_publish_callback_set(mosq, my_publish_callback);
-
-    if ((rc = mosquitto_connect(mosq, 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(mosq);
-    sprintf(buf, "1");
-    rc = mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, 1);
-#ifdef HAVE_WIRINGPI_H
-//    setBacklight(0);
-#endif
-
-    /*
-     * Report alias names
-     */
-    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
-	old1 = tmp1->next;
-
-	alias = xstrcpy((char *)"/raw/");
-	alias = xstrcat(alias, hostname);
-	alias = xstrcat(alias, (char *)"/thermometers/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(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
-	    if (rc == MOSQ_ERR_NO_CONN)
-		mosquitto_reconnect(mosq);
-	    else
-		syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
-	}
-
-	free(alias);
-	alias = NULL;
-    }
-
-    if (debug)
-	fprintf(stdout, (char *)"Enter loop, connected %d\n", connected);
-
-    do {
-	if (status == STATUS_CONNACK_RECVD) {
-#ifdef HAVE_WIRINGPI_H
-	    lcdupdate = FALSE;
-#endif
-
-	    /*
-	     * 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");
-		alias = xstrcpy((char *)"/raw/");
-		alias = xstrcat(alias, hostname);
-		alias = xstrcat(alias, (char *)"/thermometers/w1/");
-		alias = xstrcat(alias, tmp1->master);
-		alias = xstrcat(alias, (char *)"/");
-		alias = xstrcat(alias, tmp1->name);
-		alias = xstrcat(alias, (char *)"/temperature");
-
-		/*
-		 * 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.
-			    	 */
-			    	sprintf(buf, "%.1f", temp / 1000.0);
-			    	if ((rc = mosquitto_publish(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
-			            if (rc == MOSQ_ERR_NO_CONN)
-				    	mosquitto_reconnect(mosq);
-			    	    else
-				    	syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
-			    	}
-			    } 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;
-#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;
-		free(alias);
-		alias = 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);
-		old1 = tmp1->next;
-		tmp1 = old1;
-		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) {
-		/*
-		 * Final publish 0 to clients/<hostname>/thermometers/state
-		 */
-		sprintf(buf, "0");
-		mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, true);
-		last_mid = mid_sent;
-		status = STATUS_WAITING;
-#ifdef HAVE_WIRINGPI_H
-		lcdClear(lcdHandle);
-		lcdPosition(lcdHandle, 0, 0);
-		lcdPuts(lcdHandle, "Shuting down ...");
-#endif
-	    }
-
-	    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(mosq);
-		disconnect_sent = true;
-	    }
-	    usleep(100000);
-	}
-	rc = MOSQ_ERR_SUCCESS;
-
-    } while (rc == MOSQ_ERR_SUCCESS && connected);
-
-    if (debug)
-	fprintf(stdout, (char *)"Out of loop\n");
-
-    mosquitto_loop_stop(mosq, false);
-    mosquitto_destroy(mosq);
-    mosquitto_lib_cleanup();
-
-#ifdef HAVE_WIRINGPI_H
-    stopLCD();
-#endif
-
-    return rc;
-}
-
--- a/thermometers/main.h	Sun May 25 16:39:54 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-#ifndef	_MAIN_H
-#define	_MAIN_H
-
-
-#define TRUE 1
-#define FALSE 0
-
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermometers/rdconfig.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,350 @@
+/*****************************************************************************
+ * 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"
+
+
+bool		debug = FALSE;
+static char	*mypath;
+static char	*k, *v;
+static int	linecnt = 0;
+sys_config	Config;			/* System configuration		*/
+
+
+
+static int getstr(char **);
+static int getint(char **);
+static int getw1(char **);
+#ifdef HAVE_WIRINGPI_H
+static int getrcs(char **);
+#endif
+//static int getbyt(char **);
+//static int gethex(char **);
+
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+
+/*
+ * System configuration table
+ */
+key_list keytab[] = {
+    {(char *)"mosq_host",	getstr,		&Config.mosq_host},
+    {(char *)"mosq_port",	getint,		(char **)&Config.mosq_port},
+    {(char *)"w1therm",		getw1,		(char **)&Config.w1therms},
+#ifdef HAVE_WIRINGPI_H
+    {(char *)"lcd_cols",	getint,		(char **)&Config.lcd_cols},
+    {(char *)"lcd_rows",	getint,		(char **)&Config.lcd_rows},
+    {(char *)"rx433",		getint,		(char **)&Config.rx433},
+    {(char *)"tx433",		getint,		(char **)&Config.tx433},
+    {(char *)"rcswitch",	getrcs,		(char **)&Config.rcswitch},
+#endif
+    {NULL,			NULL,		NULL}
+};
+
+
+
+void killconfig(void)
+{
+    w1_therm	*tmp1, *old1;
+#ifdef HAVE_WIRINGPI_H
+    rc_switch	*tmp2, *old2;
+#endif
+
+    if (Config.name)
+	free(Config.name);
+    Config.name = NULL;
+
+    if (Config.mosq_host)
+	free(Config.mosq_host);
+    Config.mosq_host= (char *)"localhost";
+    Config.mosq_port = 1883;
+
+    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
+	old1 = tmp1->next;
+	if (tmp1->master)
+	    free(tmp1->master);
+	if (tmp1->name)
+	    free(tmp1->name);
+	if (tmp1->alias)
+	    free(tmp1->alias);
+	free(tmp1);
+    }
+    Config.w1therms = NULL;
+    Config.my_port = 6554;
+
+#ifdef HAVE_WIRINGPI_H
+    Config.lcd_cols = 16;
+    Config.lcd_rows = 2;
+    Config.rx433 = -1;
+    Config.tx433 = -1;
+
+    for (tmp2 = Config.rcswitch; tmp2; tmp2 = old2) {
+	old2 = tmp2->next;
+	if (tmp2->address)
+	    free(tmp2->address);
+	tmp2->address = NULL;
+	if (tmp2->alias)
+	    free(tmp2->alias);
+	tmp2->alias = NULL;
+	free(tmp2);
+    }
+    Config.rcswitch = NULL;
+
+#endif
+}
+
+
+
+int rdconfig(char *config) 
+{
+    char	buf[256], *p;
+    FILE	*fp;
+    int		i, rc = 0;
+
+    killconfig();
+
+    /*
+     * Search config file
+     */
+    mypath = xstrcpy(getenv((char *)"HOME"));
+    mypath = xstrcat(mypath, (char *)"/mbsepi-apps/");
+    mypath = xstrcat(mypath, config);
+    if ((fp = fopen(mypath, "r")) == NULL) {
+	/*
+	 * Not in the users home directory
+	 */
+	free(mypath);
+	mypath = xstrcpy((char *)"/etc/mbsepi-apps/");
+	mypath = xstrcat(mypath, config);
+	if ((fp = fopen(mypath, "r")) == NULL) {
+	    /*
+	     * Try /usr/local/etc
+	     */
+	    free(mypath);
+	    mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/");
+	    mypath = xstrcat(mypath, config);
+	    if ((fp = fopen(mypath, "r")) == NULL) {
+		syslog(LOG_NOTICE, "rdconfig: could not open %s", mypath);
+		return 1;
+	    }
+	}
+    }
+
+    linecnt = 0;
+    while (fgets(buf, sizeof(buf) -1, fp)) {
+	linecnt++;
+	if (*(p = buf + strlen(buf) -1) != '\n') {
+	    syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf);
+	    rc = 1;
+	    break;
+	}
+	*p-- = '\0';
+	while ((p >= buf) && isspace(*p))
+	    *p-- = '\0';
+	k = buf;
+	while (*k && isspace(*k))
+	    k++;
+	p = k;
+	while (*p && !isspace(*p))
+	    p++;
+	*p++='\0';
+	v = p;
+	while (*v && isspace(*v)) 
+	    v++;
+
+	if ((*k == '\0') || (*k == '#')) {
+	    continue;
+	}
+
+	for (i = 0; keytab[i].key; i++)
+	    if (strcasecmp(k,keytab[i].key) == 0)
+		break;
+
+	if (keytab[i].key == NULL) {
+	    syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - unknown keyword", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+	    rc = 1;
+	    break;
+	} else if ((keytab[i].prc(keytab[i].dest))) {
+	    rc = 1;
+	    break;
+	}
+
+    }
+    fclose(fp);
+
+    free(mypath);
+    mypath = NULL;
+
+    return rc;
+}
+
+
+
+static int getstr(char **dest)
+{
+    if (debug)
+	syslog(LOG_NOTICE, "rdconfig: getstr: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+
+    *dest = xstrcpy(v);
+    return 0;
+}
+
+
+
+static int getint(char **dest)
+{
+    if (debug)
+	syslog(LOG_NOTICE, "rdconfig: getint: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+
+    if (strspn(v,"0123456789") != strlen(v)) 
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad numeric", mypath, linecnt, MBSE_SS(k), MBSE_SS(v));
+    else 
+	*((int*)dest)=atoi(v);
+    return 0;
+}
+
+
+
+static int getw1(char **dest)
+{
+    char	*p, *q = NULL, *r = NULL;
+    w1_therm	**tmpm;
+    int		rc = 0, tmpp;
+
+    for (p = v; *p && !isspace(*p); p++);
+    if (*p)
+	*p++ = '\0';
+    while (*p && isspace(*p))
+	p++;
+    if (*p == '\0') {
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
+	return 1;
+    }
+
+    for (q = p; *q && !isspace(*q); q++);
+    if (*q && isspace(*q)) {
+	if (*q)
+	    *q++ = '\0';
+	while (*q && isspace(*q))
+	    q++;
+
+	for (r = q; *r && !isspace(*r); r++);
+	if (*r)
+	    *r++ = '\0';
+	rc = sscanf(p, "%d", &tmpp);
+	if (rc != 1) {
+	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s is not a integer value", mypath, linecnt, p);
+	    return 1;
+	}
+	if (debug)
+	    syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s %d %s %s", mypath, linecnt, v, tmpp, q, r);
+    }
+
+    for (tmpm = (w1_therm**)dest; *tmpm; tmpm=&((*tmpm)->next));
+    (*tmpm) = (w1_therm *) xmalloc(sizeof(w1_therm));
+    (*tmpm)->next = NULL;
+    (*tmpm)->master = xstrcpy(v);
+    (*tmpm)->bus = tmpp;
+    (*tmpm)->name = xstrcpy(q);
+    (*tmpm)->alias = xstrcpy(r);
+    (*tmpm)->present = 0;
+    (*tmpm)->lastval = 0;
+    (*tmpm)->update = 0;
+
+    return 0;
+}
+
+
+
+#ifdef HAVE_WIRINGPI_H
+static int getrcs(char **dest)
+{
+    char        *p, *q = NULL, *r = NULL;
+    rc_switch   **tmpm;
+
+    for (p = v; *p && !isspace(*p); p++);
+	if (*p)
+	    *p++ = '\0';
+    while (*p && isspace(*p))
+	p++;
+    if (*p == '\0') {
+	syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt);
+	return 1;
+    }
+
+    for (q = p; *q && !isspace(*q); q++);
+    if (*q && isspace(*q)) {
+	if (*q)
+	    *q++ = '\0';
+	while (*q && isspace(*q))
+	    q++;
+
+	for (r = q; *r && !isspace(*r); r++);
+	if (*r)
+	    *r++ = '\0';
+	if (debug)
+	    syslog(LOG_NOTICE, "rdconfig: getrcs: %s(%d): %s %s", mypath, linecnt, v, p);
+    }
+
+    for (tmpm = (rc_switch**)dest; *tmpm; tmpm=&((*tmpm)->next));
+    (*tmpm) = (rc_switch *) xmalloc(sizeof(rc_switch));
+    (*tmpm)->next = NULL;
+    (*tmpm)->address = xstrcpy(v);
+    (*tmpm)->alias = xstrcpy(p);
+
+    return 0;
+}
+#endif
+
+
+/*
+static int getbyt(char **dest)
+{
+    Log_Msg("[rdconfig] getbyt: %s(%d): %s %s", mypath, linecnt, k, v);
+    if (strspn(v,"0123456789") != strlen(v))
+	Log_Msg("[rdconfig] %s(%d): %s %s - bad numeric", mypath, linecnt, S(k), S(v));
+    else
+	*((Uint8*)dest)=atoi(v);
+    return 0;
+}
+*/
+
+
+/*
+static int gethex(char **dest)
+{
+    unsigned int    val = 0;
+    int		    rc;
+
+    Log_Msg("[rdconfig] gethex: %s(%d): %s %s", mypath, linecnt, k, v);
+    rc = sscanf(v, "%08x", &val);
+    if (rc != 1) {
+	Log_Msg("[rdconfig] %s(%d): %s %s - bad hex value", mypath, linecnt, S(k), S(v));
+	return 1;
+    }
+    *((int*)dest) = val;
+
+    return 0;
+}
+*/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermometers/thermometers.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,553 @@
+/*****************************************************************************
+ * 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"
+
+
+#define STATUS_CONNECTING 0
+#define STATUS_CONNACK_RECVD 1
+#define STATUS_WAITING 2
+
+/* Global variables for use in callbacks. */
+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;
+static bool		my_shutdown = false;
+static pid_t		pgrp, mypid;
+
+extern bool		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;
+}
+
+
+
+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 (my_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);
+}
+
+
+
+#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, "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)
+{
+    char                *id = NULL, *state = NULL;
+    struct mosquitto    *mosq = NULL;
+    char                hostname[256], buf[1024];
+    int                 temp, rc, deviation, keepalive = 60;
+#ifdef HAVE_WIRINGPI_H
+    int			lcdupdate;
+#endif
+    unsigned int        max_inflight = 20;
+    char                err[1024];
+    w1_therm		*tmp1, *old1;
+    char		*device, *alias, line[60], *p = NULL;
+    FILE		*fp;
+
+    /*
+     * Initialize mosquitto communication
+     */
+    mosquitto_lib_init();
+
+    /*
+     * Build MQTT id
+     */
+    hostname[0] = '\0';
+    gethostname(hostname, 256);
+    hostname[255] = '\0';
+
+    id = xstrcpy((char *)"thermometers/");
+    id = xstrcat(id, hostname);
+    if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH) {
+	/*
+	 * Enforce maximum client id length of 23 characters
+	 */
+	id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
+    }
+
+    mosq = mosquitto_new(id, true, NULL);
+    if(!mosq) {
+	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(mosq, my_log_callback);
+    }
+
+    /*
+     * Set our will
+     */
+    state = xstrcpy((char *)"clients/");
+    state = xstrcat(state, hostname);
+    state = xstrcat(state, (char *)"/thermometers/state");
+    sprintf(buf, "0");
+    if ((rc = mosquitto_will_set(mosq, 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(mosq, max_inflight);
+    mosquitto_connect_callback_set(mosq, my_connect_callback);
+    mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
+    mosquitto_publish_callback_set(mosq, my_publish_callback);
+
+    if ((rc = mosquitto_connect(mosq, 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(mosq);
+    sprintf(buf, "1");
+    rc = mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, 1);
+#ifdef HAVE_WIRINGPI_H
+//    setBacklight(0);
+#endif
+
+    /*
+     * Report alias names
+     */
+    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
+	old1 = tmp1->next;
+
+	alias = xstrcpy((char *)"/raw/");
+	alias = xstrcat(alias, hostname);
+	alias = xstrcat(alias, (char *)"/thermometers/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(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
+	    if (rc == MOSQ_ERR_NO_CONN)
+		mosquitto_reconnect(mosq);
+	    else
+		syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
+	}
+
+	free(alias);
+	alias = NULL;
+    }
+
+    if (debug)
+	fprintf(stdout, (char *)"Enter loop, connected %d\n", connected);
+
+    do {
+	if (status == STATUS_CONNACK_RECVD) {
+#ifdef HAVE_WIRINGPI_H
+	    lcdupdate = FALSE;
+#endif
+
+	    /*
+	     * 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");
+		alias = xstrcpy((char *)"/raw/");
+		alias = xstrcat(alias, hostname);
+		alias = xstrcat(alias, (char *)"/thermometers/w1/");
+		alias = xstrcat(alias, tmp1->master);
+		alias = xstrcat(alias, (char *)"/");
+		alias = xstrcat(alias, tmp1->name);
+		alias = xstrcat(alias, (char *)"/temperature");
+
+		/*
+		 * 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.
+			    	 */
+			    	sprintf(buf, "%.1f", temp / 1000.0);
+			    	if ((rc = mosquitto_publish(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
+			            if (rc == MOSQ_ERR_NO_CONN)
+				    	mosquitto_reconnect(mosq);
+			    	    else
+				    	syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
+			    	}
+			    } 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;
+#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;
+		free(alias);
+		alias = 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);
+		old1 = tmp1->next;
+		tmp1 = old1;
+		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) {
+		/*
+		 * Final publish 0 to clients/<hostname>/thermometers/state
+		 */
+		sprintf(buf, "0");
+		mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, true);
+		last_mid = mid_sent;
+		status = STATUS_WAITING;
+#ifdef HAVE_WIRINGPI_H
+		lcdClear(lcdHandle);
+		lcdPosition(lcdHandle, 0, 0);
+		lcdPuts(lcdHandle, "Shuting down ...");
+#endif
+	    }
+
+	    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(mosq);
+		disconnect_sent = true;
+	    }
+	    usleep(100000);
+	}
+	rc = MOSQ_ERR_SUCCESS;
+
+    } while (rc == MOSQ_ERR_SUCCESS && connected);
+
+    if (debug)
+	fprintf(stdout, (char *)"Out of loop\n");
+
+    mosquitto_loop_stop(mosq, false);
+    mosquitto_destroy(mosq);
+    mosquitto_lib_cleanup();
+
+#ifdef HAVE_WIRINGPI_H
+    stopLCD();
+#endif
+
+    return rc;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermometers/thermometers.h	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,154 @@
+#ifndef	_THERMOMETERS_H
+#define	_THERMOMETERS_H
+
+
+#define TRUE 1
+#define FALSE 0
+
+#include "../config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <getopt.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <poll.h>
+
+
+/* mosquitto */
+#include <mosquitto.h>
+
+#ifdef HAVE_WIRINGPI_H
+/* wiringPi */
+#include <wiringPi.h>
+#include <pcf8574.h>
+#include <lcd.h>
+
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+#define MBSE_SS(x) (x)?(x):"(null)"
+
+/* rdconfig.c */
+typedef struct _key_list {
+    char	*key;
+    int		(*prc)(char **);
+    char	**dest;
+} key_list;
+
+typedef struct _w1_therm {
+    struct _w1_therm    *next;
+    char                *master;                /* Master for this device       */
+    int                 bus;                    /* Reserved for ds2482-800      */
+    char                *name;                  /* Name of this device          */
+    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 {
+    struct _rc_switch	*next;
+    char		*address;		/* Address code			*/
+    char		*alias;			/* Friendly name		*/
+} rc_switch;
+
+typedef struct _sys_config {
+    char		*name;			/* Configuration name		*/
+    char		*mosq_host;		/* mosquitto server hostname	*/
+    int			mosq_port;		/* mosquitto server port	*/
+    int			my_port;		/* my client/server port	*/
+    w1_therm		*w1therms;		/* 1-wire temp sensors		*/
+#ifdef HAVE_WIRINGPI_H
+    int			lcd_cols;		/* LCD display columns		*/
+    int			lcd_rows;		/* LCD display rows		*/
+    int			rx433;			/* 433 MHz receiver pin		*/
+    int			tx433;			/* 433 MHz transmitter pin	*/
+    rc_switch		*rcswitch;		/* 433 MHz RC Power switches	*/
+#endif
+} sys_config;
+
+
+void killconfig(void);
+int  rdconfig(char *);
+
+
+/* xutil.c */
+char *xmalloc(size_t);
+char *xstrcpy(char *);
+char *xstrcat(char *, char *);
+
+
+#ifdef HAVE_WIRINGPI_H
+
+/* lcd-pcf8574.c */
+// Defines for the pcf8574 Pi LCD interface board
+#define AF_BASE         100
+
+#define AF_RS           (AF_BASE + 0)
+#define AF_RW           (AF_BASE + 1)
+#define AF_E            (AF_BASE + 2)
+#define AF_BACKLIGHT    (AF_BASE + 3)
+#define AF_DB4          (AF_BASE + 4)
+#define AF_DB5          (AF_BASE + 5)
+#define AF_DB6          (AF_BASE + 6)
+#define AF_DB7          (AF_BASE + 7)
+
+void setBacklight (int);
+int  initLCD (int, int);
+void mb_lcdPutchar(const int, unsigned char);
+void mb_lcdPuts(const int, const char *);
+void mb_lcdClear(const int);
+
+
+/* logger.c */
+void logger(char *, char *, char *);
+
+
+/* rc-switch.c */
+int  toggleSwitch(char *);
+int  toggleTypeA(char *, char *, bool);
+int  toggleTypeB(int, int, bool);
+int  toggleTypeC(char, int, int, bool);
+int  toggleTypeE(char, int, bool);
+
+void enableReceiveIRQ(int interrupt);
+void enableReceive(void);
+void disableReceive(void);
+bool available(void);
+void resetAvailable(void);
+
+unsigned long getReceivedValue(void);
+unsigned int getReceivedBitlength(void);
+unsigned int getReceivedDelay(void);
+unsigned int getReceivedProtocol(void);
+unsigned int *getReceivedRawdata(void);
+
+void enableTransmit(int);
+void disableTransmit(void);
+
+char *dec2binWzerofill(unsigned long, unsigned int);
+
+
+#endif
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermometers/xutil.c	Sun May 25 22:06:56 2014 +0200
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * Copyright (C) 2008-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"
+
+
+char *xmalloc(size_t size)
+{
+    char *tmp;
+
+    tmp = malloc(size);
+    if (!tmp) 
+	abort();
+			            
+    return tmp;
+}
+
+
+
+char *xstrcpy(char *src)
+{
+    char    *tmp;
+
+    if (src == NULL) 
+	return(NULL);
+    tmp = xmalloc(strlen(src)+1);
+    strcpy(tmp, src);
+    return tmp;
+}
+
+
+
+char *xstrcat(char *src, char *add)
+{
+    char    *tmp;
+    size_t  size = 0;
+
+    if ((add == NULL) || (strlen(add) == 0))
+	return src;
+    if (src)
+	size = strlen(src);
+    size += strlen(add);
+    tmp = xmalloc(size + 1);
+    *tmp = '\0';
+    if (src) {
+	strcpy(tmp, src);
+	free(src);
+    }
+    strcat(tmp, add);
+    return tmp;
+}
+
+

mercurial