Initial commit
authorEoin Meehan <eoin.meehan@cs.tcd.ie>
Fri, 07 May 2010 12:04:06 +0100
changeset 0 55f67f57d26d
child 1 3ca5add34a32
Initial commit
Makefile
installpbm
pbm
pbmd
pbmd.c
sleeprtc.sh
stbylong.sh
stbyshort.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,11 @@
+OBJECTS=manager ifkit phidgetsbclist testlightmeter
+CFLAGS=-g -O0 -Wall -I../
+LIBS= -lphidget21 -lpthread -ldl
+
+all: $(OBJECTS)
+
+%: %.c
+	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
+clean:
+	-rm *.o $(OBJECTS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installpbm	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+cp ./stbyshort.sh /etc
+chmod +x          /etc/stbyshort.sh
+chown root        /etc/stbyshort.sh
+chgrp root        /etc/stbyshort.sh
+echo "Copied stbyshort.sh to /etc ..."
+
+cp ./stbylong.sh /etc
+chmod +x         /etc/stbylong.sh
+chown root       /etc/stbylong.sh
+chgrp root       /etc/stbylong.sh
+echo "Copied stbylong.sh to /etc ..."
+
+cp ./sleeprtc.sh /etc
+chmod +x   /etc/stbylong.sh
+chown root /etc/sleeprtc.sh
+chgrp root /etc/sleeprtc.sh
+echo "Copied sleeprtc.sh to /etc ..."
+
+cp ./pbmd  /usr/sbin
+chmod +x   /usr/sbin/pbmd
+chown root /usr/sbin/pbmd
+chgrp root /usr/sbin/pbmd
+echo "Copied pbmd to /usr/sbin ..."
+
+cp ./pbm   /etc/init.d
+chmod +x   /etc/init.d/pbm
+chown root /etc/init.d/pbm
+chgrp root /etc/init.d/pbm
+echo "Copied pbm to /etc/init.d ..."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pbm	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,156 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          pbm
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Example initscript
+# Description:       This file should be used to construct scripts to be
+#                    placed in /etc/init.d.
+### END INIT INFO
+
+# Author: Eoin Meehan <eoin.meehan@cs.tcd.ie>
+#
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="power manager daemon"
+NAME=pbmd
+DAEMON=/usr/sbin/$NAME
+DAEMON_ARGS="/var/log/battery.log /var/log/battery-snapshot.log /etc/bootflag 60 0"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start -b --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+       ;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+	  	# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
Binary file pbmd has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pbmd.c	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,637 @@
+// pbm.c
+//
+// The Program Formerly Known as pollbatterymonitor.c
+//
+// The Phidget Interface Kit with the integrated LCD screen is actually
+// two separate devices and so you must set up two handles and two sets of 
+// handlers
+//
+// This program connects to a Phidget with LCD which has an ammeter and a
+// voltmeter attached. It reads the both and writes the results to a log file
+// It then writes summary info to a "snapshot" file including a state.
+//
+//
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <phidget21.h>
+#include <time.h>
+#include <stdlib.h>
+
+#define INIT       0		// Initialised (first run or reset manually)
+#define STBYLONG   1		// Standby 180 - reboot, check voltage, sleep 3 hours
+#define STBYSHORT  2		// Standby 30 - boot, check voltage, sleep 30 mins
+#define OVERRIDE   3		// manually started - run 30 mins then sleep
+#define SLEEP      4 		// Sleep during the night
+#define UP         9		// Running normally - dont sleep
+#define GREEN   1150		// Voltage level for normal running
+#define AMBER 	1129		// Voltage level at which we must go asleep
+#define SLEEPTIMESTART "22:00"	// Time to start sleeping
+#define SLEEPTIMEEND   "06:00" 	// Time to end sleeping
+
+void display_generic_properties(CPhidgetHandle phid)
+{
+	int sernum, version;
+	const char *deviceptr;
+	CPhidget_getDeviceType(phid, &deviceptr);
+	CPhidget_getSerialNumber(phid, &sernum);
+	CPhidget_getDeviceVersion(phid, &version);
+
+	printf("%s\n", deviceptr);
+	printf("Version: %8d SerialNumber: %10d\n", version, sernum);
+	return;
+}
+
+int display_properties(CPhidgetTextLCDHandle phid)
+{
+	int serialNo, version, numRows, numColumns, backlight, cursor, contrast, cursor_blink;
+	const char* ptr;
+
+	CPhidget_getDeviceType((CPhidgetHandle)phid, &ptr);
+	CPhidget_getSerialNumber((CPhidgetHandle)phid, &serialNo);
+	CPhidget_getDeviceVersion((CPhidgetHandle)phid, &version);
+
+	CPhidgetTextLCD_getRowCount (phid, &numRows);
+	CPhidgetTextLCD_getColumnCount (phid, &numColumns);
+	CPhidgetTextLCD_getBacklight (phid, &backlight);
+	CPhidgetTextLCD_getContrast (phid, &contrast);
+	CPhidgetTextLCD_getCursorOn (phid, &cursor);
+	CPhidgetTextLCD_getCursorBlink (phid, &cursor_blink);
+
+	printf("%s\n", ptr);
+	printf("Serial Number: %10d\nVersion: %8d\n", serialNo, version);
+	printf("# Rows: %d\n# Columns: %d\n", numRows, numColumns);
+	printf("Current Contrast Level: %d\nBacklight Status: %d\n", contrast, backlight);
+	printf("Cursor Status: %d\nCursor Blink Status: %d\n", cursor, cursor_blink);
+
+	return 0;
+}
+
+
+int IFK_DetachHandler(CPhidgetHandle IFK, void *userptr)
+{
+	printf("IFK Detach handler ran!\n");
+	return 0;
+}
+
+int IFK_ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
+{
+	printf("IFK Error handler ran!\n");
+	return 0;
+}
+
+int IFK_OutputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+	printf("Output %d is %d\n", Index, Value);
+	return 0;
+}
+
+int IFK_InputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+	printf("Input %d is %d\n", Index, Value);
+	return 0;
+}
+
+int IFK_SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+	float fValue;
+	int oValue, rValue;
+
+	rValue = 0;
+	oValue = Value;
+
+
+	if (Index == 0) {
+		fValue = Value;				// Sensor 0 is Amps - adj accordingly
+		fValue = (fValue*13.2)-37.8787;		// (SensorValue / 13.2) - 37.8787
+		Value = fValue;
+		}				
+
+	return 0;
+}
+
+
+int IFK_AttachHandler(CPhidgetHandle IFK, void *userptr)
+{
+	CPhidgetInterfaceKit_setSensorChangeTrigger((CPhidgetInterfaceKitHandle)IFK, 0, 0);
+	printf("IFK Attach handler ran!\n");
+	return 0;
+}
+
+int LCD_AttachHandler(CPhidgetHandle IFK, void *userptr)
+{
+	printf("LCD Attach handler ran!\n");
+	return 0;
+}
+
+int LCD_DetachHandler(CPhidgetHandle IFK, void *userptr)
+{
+	printf("LCD Detach handler ran!\n");
+	return 0;
+}
+
+int LCD_ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
+{
+	printf("LCD Error handler ran!\n");
+	return 0;
+}
+
+
+int getVoltage(CPhidgetInterfaceKitHandle IFK, int voltIndex, int *Voltage)
+{
+	float fValue = 0, avgValue = 0;
+	int Value= 0, i = 0;
+
+	CPhidgetInterfaceKit_setRatiometric(IFK, PFALSE);		// set to non-ratio
+	sleep(2);							// wait at least 800ms to settle
+	CPhidgetInterfaceKit_getSensorRawValue(IFK, voltIndex, &Value);	// Voltmeter
+
+	// Calibration							// this is zero point calibration.
+	Value = Value + 5;
+	// End calibration
+
+	// get an average over 5 readings to allow for sensor noise. 1 per second for 5 seconds
+
+	for (i = 0; i < 5 ; i++)
+	{
+		fValue = Value;
+		fValue = (((fValue/4.095)*0.06)-30)*100;    // multiply raw value and up by 100 to keep
+		avgValue = avgValue + fValue;
+		sleep (1);
+	}
+		avgValue = avgValue / 5;
+		*Voltage = avgValue;
+
+//	printf("Volts value %d\n", Value);
+
+	return 0;
+}
+
+int getAmps(CPhidgetInterfaceKitHandle IFK, int ampIndex, int *Amps)
+{
+	float fValue;
+	int Value,nValue;
+
+		CPhidgetInterfaceKit_setRatiometric (IFK, PTRUE);		// set to ratiometric
+		sleep(2);							// wait at least 800ms
+		CPhidgetInterfaceKit_getSensorRawValue(IFK, ampIndex, &Value);	// Ampmeter
+		CPhidgetInterfaceKit_getSensorValue(IFK, ampIndex, &nValue);
+
+		// Calibration
+		Value = Value + 2;
+		// End calibration
+
+		fValue = Value;
+		fValue = (((fValue/4.095)/13.2)-37.8787)*1000;	// multiply raw value to get amps
+		*Amps = fValue;
+
+//	printf("Amps value Raw %d Normal %d\n", Value, nValue);
+	return 0;
+}
+
+int getLux(CPhidgetInterfaceKitHandle IFK, int luxIndex, int *Lux)
+{
+	int Value;
+
+		CPhidgetInterfaceKit_setRatiometric(IFK, PFALSE);		// set to non-ratio
+		sleep(2);							// wait at least 800ms
+		CPhidgetInterfaceKit_getSensorValue(IFK, luxIndex, &Value);	// Voltmeter
+
+		// Calibration
+		// None required
+		// End calibration
+
+		*Lux = Value;
+
+//	printf("Volts value %d\n", Value);
+	return 0;
+}
+
+
+int updateSnapshotfile(char *SNAPSHOTFILE, int newState, int Voltage, int Amps, int Lux)
+{
+	// Snapshot file is a single line file, overwritten each time with the current and latest values
+  	time_t rawtime;
+  	struct tm * timeinfo;
+  	char timeStr [80];
+
+  	time ( &rawtime );
+  	timeinfo = localtime ( &rawtime );
+
+  	strftime (timeStr,80,"%Y-%m-%d,%H:%M:%S",timeinfo);
+
+      	FILE *filesnap = fopen( SNAPSHOTFILE, "w" );			// Open file (delete previous)
+
+       	if (filesnap == 0)		// Aaargh! Problem ...
+       	{
+        	printf( "Could not open the snapshot file\n" );
+      	}
+     	  else 
+      	  {
+		fprintf(filesnap, "%d,%s,%d,%d,%d\n", newState, timeStr, Voltage, Amps, Lux);
+		fflush(filesnap);
+	  }
+	fclose( filesnap );
+
+	return 0;
+}
+
+
+
+int updateLogfile(FILE *filelog, int Voltage, int Amps, int Lux)
+{
+  	time_t rawtime;
+  	struct tm * timeinfo;
+  	char timeStr [80];
+
+  	time ( &rawtime );
+  	timeinfo = localtime ( &rawtime );
+
+  	strftime (timeStr,80,"%Y-%m-%d,%H:%M:%S",timeinfo);
+
+	fprintf(filelog, "%s,%d,%d,%d\n", timeStr, Voltage, Amps, Lux);
+	fflush(filelog);
+
+	return 0;
+}
+
+
+// getTimeString returns the time in a string in the form "HH:MM". It takes the current
+// time and adds the wakeTime to it. This can also be used to simply return the current time if the
+// wakeTime is 0.
+
+int getTimeString (int wakeTime, char *wakeTimeStr)
+{
+  	time_t rawtime;
+  	struct tm * timeinfo;
+
+  	time ( &rawtime );
+	rawtime = rawtime + (wakeTime * 60);
+  	timeinfo = localtime ( &rawtime );
+
+ // 	strftime (wakeTimeStr,80,"%Y-%m-%d,%H:%M:%S",timeinfo);
+ 	strftime (wakeTimeStr,20,"%H:%M",timeinfo);
+
+	return 0;
+}
+
+int getState(char *SNAPSHOTFILE, int previousState, char *bootflag)
+{
+	// Snapshot file is a single line file, overwritten each time with the current and latest values
+
+      	FILE *filesnap = fopen( SNAPSHOTFILE, "r" );			// Open file (delete previous)
+
+       	if (filesnap == 0)		// Aaargh! Problem ...
+       	{
+        	printf( "getState: Could not open the snapshot file to retrieve state\n" );
+      	}
+     	  else 
+      	  {
+		//fprintf(filesnap, "%s,%d,%d,%d\n", timeStr, Voltage, Amps, Lux);
+		//fflush(filesnap);
+	  }
+	fclose( filesnap );
+
+	return 0;
+}
+
+int getnewState(int Voltage, char *bootflag, int *newState)
+{
+	char *timeStr = malloc(20);
+
+	int localState = 0;
+
+	printf ("In getnewState: Bootflag %s Voltage %d\n", bootflag, Voltage);
+
+	*newState = localState;				// Just to be sure its 0}
+
+	getTimeString (0, timeStr);			// Use this to return current time as a string
+
+	if (strncmp(bootflag, "S",1) != 0) {		// Anything except an S will mean manual start
+	    localState = OVERRIDE;
+	    }
+	else if (strcmp(timeStr, SLEEPTIMESTART) > 0 || strcmp(timeStr, SLEEPTIMEEND) < 0) {
+	    localState = SLEEP;
+            }
+	else if (Voltage >= GREEN) {
+	    localState = UP;
+            }
+	else if (Voltage >= AMBER) {
+	    localState = STBYSHORT;
+	    }
+        else {
+	    localState = STBYLONG;
+	    } 
+
+	*newState = localState;				// and set it across the wormhole
+
+	return 0;
+}
+
+int test_interfacekit(FILE *filelog, char *SNAPSHOTFILE, char * bootflag, time_t boottime, int Sleep, int testVoltage)
+{
+	int LUXINDEX=2;
+	int VOLTINDEX=1;
+	int AMPINDEX=0;
+
+	int numInputs, numOutputs, numSensors;
+	int err;
+	int lightTrigger;
+	int Voltage = 0, Amps = 0, Lux = 0;
+	int tts;
+	int newState = 0;
+	int ret;
+
+  	char buffer1 [80];
+  	char buffer2 [80];
+	char *wakeTimeStr = malloc(20);
+
+	char *stateDesc[10];
+
+	time_t timenow;
+
+	stateDesc[0] = "Initialise";
+	stateDesc[1] = "STBYLONG";
+	stateDesc[2] = "STBYSHORT";
+	stateDesc[3] = "OVERRIDE";
+	stateDesc[4] = "SLEEP";
+	stateDesc[9] = "UP";
+
+	CPhidgetInterfaceKitHandle IFK = 0;
+	CPhidgetInterfaceKit_create(&IFK);
+
+	CPhidgetTextLCDHandle LCD = 0;
+	CPhidgetTextLCD_create (&LCD);
+
+	//CPhidget_enableLogging(PHIDGET_LOG_VERBOSE, NULL);
+
+	// Set up handlers for the Interface Kit
+
+	CPhidget_set_OnAttach_Handler((CPhidgetHandle)IFK, IFK_AttachHandler, NULL);
+	CPhidget_set_OnDetach_Handler((CPhidgetHandle)IFK, IFK_DetachHandler, NULL);
+	CPhidget_set_OnError_Handler((CPhidgetHandle)IFK, IFK_ErrorHandler, NULL);
+
+	// Set up handlers for the TextLCD
+
+	CPhidget_set_OnAttach_Handler((CPhidgetHandle)LCD, LCD_AttachHandler, NULL);
+	CPhidget_set_OnDetach_Handler((CPhidgetHandle)LCD, LCD_DetachHandler, NULL);
+	CPhidget_set_OnError_Handler((CPhidgetHandle)LCD, LCD_ErrorHandler, NULL);
+			
+	CPhidget_open((CPhidgetHandle)IFK, -1);
+	CPhidget_open((CPhidgetHandle)LCD, -1);
+
+	//wait 5 seconds for attachment of the Interface Kit
+	printf("Waiting for IFK to be attached...\n");
+	if((err = CPhidget_waitForAttachment((CPhidgetHandle)IFK, 5000)) != EPHIDGET_OK )
+	{
+		const char *errStr;
+		CPhidget_getErrorDescription(err, &errStr);
+		printf("Error waiting for IFK attachment: (%d): %s\n",err,errStr);
+		goto exit;
+	}
+	
+	display_generic_properties((CPhidgetHandle)IFK);
+	CPhidgetInterfaceKit_getOutputCount((CPhidgetInterfaceKitHandle)IFK, &numOutputs);
+	CPhidgetInterfaceKit_getInputCount((CPhidgetInterfaceKitHandle)IFK, &numInputs);
+	CPhidgetInterfaceKit_getSensorCount((CPhidgetInterfaceKitHandle)IFK, &numSensors);
+	
+	CPhidgetInterfaceKit_setOutputState((CPhidgetInterfaceKitHandle)IFK, 0, 1);
+
+	printf("Sensors:%d Inputs:%d Outputs:%d\n", numSensors, numInputs, numOutputs);
+
+	//get the program to wait for an TextLCD device to be attached
+	printf("Waiting for LCD to be attached...\n");
+	if((err = CPhidget_waitForAttachment((CPhidgetHandle)LCD, 10000)))
+	{
+		const char *errStr;
+		CPhidget_getErrorDescription(err, &errStr);
+		printf("Problem waiting for LCD attachment: (%d): %s\n",err,errStr);
+		return 0;
+	}
+
+	//Display the properties of the attached textlcd device
+	display_properties(LCD);
+
+
+	CPhidgetInterfaceKit_getSensorChangeTrigger (IFK, 0, &lightTrigger);
+
+
+	while(1)
+	{
+		getVoltage(IFK, VOLTINDEX, &Voltage);
+		getAmps(IFK, AMPINDEX, &Amps);
+		getLux(IFK, LUXINDEX, &Lux);
+
+
+		if (testVoltage != 0) {
+			Voltage = testVoltage;
+		}
+
+		getnewState (Voltage, bootflag, &newState);
+
+		updateLogfile (filelog, Voltage, Amps, Lux);
+
+		updateSnapshotfile (SNAPSHOTFILE, newState, Voltage, Amps, Lux);
+
+	// Now Update the LCD
+
+		getTimeString (0, wakeTimeStr);
+		sprintf (buffer1, "V:%4d A:%-5d %s", Voltage, Amps,wakeTimeStr);
+		sprintf (buffer2, "%-s", stateDesc[newState]);
+
+		CPhidgetTextLCD_setDisplayString (LCD, 0, buffer1);
+		CPhidgetTextLCD_setDisplayString (LCD, 1, buffer2);
+	
+
+
+	// Do what the state demands
+	printf ("Begin main while loop: State is %s\n", stateDesc[newState]);
+
+	switch (newState)
+	{
+	case INIT:
+	    // Shouldnt be here!
+	    break;
+
+	case STBYLONG:
+	    // sleep for 3 hours, then wake, reboot
+		getTimeString (180, wakeTimeStr);
+		sprintf (buffer2, "%-s Back@%-s", stateDesc[newState], wakeTimeStr);
+
+		CPhidgetTextLCD_setDisplayString (LCD, 1, buffer2);
+		
+		ret = system ("/etc/stbylong.sh");
+		if (!ret) {
+		    printf ("STBYLONG - executing ...\n");
+		}
+		else {
+		    printf ("STBYLONG - problem kicking off STBYLONG ... not running. Error %d\n",ret);
+		}
+	    break;
+
+	case STBYSHORT:
+	    // sleep for 30 mins, then wake, reboot
+		getTimeString (30, wakeTimeStr);
+		sprintf (buffer2, "%-s Wake@%-s", stateDesc[newState], wakeTimeStr);
+
+		CPhidgetTextLCD_setDisplayString (LCD, 1, buffer2);
+		
+		ret = system ("/etc/stbyshort.sh");
+		if (!ret) {
+		    printf ("STBYSHORT - executing ...\n");
+		}
+		else {
+		    printf ("STBYSHORT - problem kicking off STBYSHORT ... not running. Error %d\n",ret);
+		}
+	    break;
+
+	case OVERRIDE:
+	    // stay up for 30 mins, then sleep, wake, reboot
+	        time (&timenow);
+		tts = 1800 - (timenow - boottime);
+		printf ("%d to sleep\n", tts);
+
+		sprintf (buffer2, "%-s Time:%d", stateDesc[newState], tts/60);
+
+		CPhidgetTextLCD_setDisplayString (LCD, 1, buffer2);
+
+		if (timenow > boottime + 1800) {
+
+		    printf ("OVERRIDE - 30 mins expired ... switching to normal mode\n");
+		    bootflag = "S";
+		    printf ("Bootflag in case OVERRIDE %s \n", bootflag);
+		}
+	    break;
+
+	case SLEEP:
+	    // We're running during night time - go to sleep
+		wakeTimeStr = SLEEPTIMEEND;
+		sprintf (buffer2, "%-s Wake@%-s", stateDesc[newState], wakeTimeStr);
+
+		CPhidgetTextLCD_setDisplayString (LCD, 1, buffer2);
+		
+		ret = system ("/etc/sleeprtc.sh");
+		if (!ret) {
+		    printf ("SLEEPRTC - executing ...\n");
+		}
+		else {
+		    printf ("SLEEPRTC - problem kicking off SLEEPRTC ... not running. Error %d\n",ret);
+		}
+	    break;
+	case UP:
+	    // normal running here
+	    // Nothing to do but continue loop
+	    break;
+	}
+
+	fflush (stdout);
+	sleep (Sleep);
+
+	}
+
+exit:
+	CPhidget_close((CPhidgetHandle)IFK);
+	CPhidget_delete((CPhidgetHandle)IFK);
+	CPhidget_close((CPhidgetHandle)LCD);
+	CPhidget_delete((CPhidgetHandle)LCD);
+
+	return 0;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+   int Sleep, testVoltage;
+   char *SNAPSHOTFILE;
+   char *bootflag = malloc(2);
+   time_t boottime;
+
+
+   if ( argc != 6 ) {							// 5 args inc program name
+            printf( "usage: %s logfile snapshotfile rebootfile sleeptime testvoltage\n", argv[0] );
+	    exit(1);
+    	}
+ 
+	// Close out stdout and point to a file cos if we are running as a demon we need to log this somewhere.
+
+	fclose(stdout);
+	fclose(stderr);
+	stdout = fopen("/var/log/pbm.log", "a");
+	stderr = fopen("/var/log/pbm.err", "a");
+
+	Sleep = atoi(argv[4]);						// Arg 4 is sleep interval
+	testVoltage = atoi(argv[5]);					// Arg 5 is used for testing
+									// - 0 is use voltmeter reading
+									// - any other value overrides
+
+	FILE *filelog = fopen( argv[1], "a" );				// Open log file
+        FILE *filesnap = fopen( argv[2], "w" );				// Open snapshot file
+
+        if ( (filelog == 0) || (filesnap == 0))	{			// Aaargh! Problem ...
+            printf( "Could not open log file or snapshot file\n" );
+	    exit(1);
+        }
+
+	fclose( filesnap );			// cos we need to overwrite it every time we write to it
+
+	// The system reboots after a sleep period to ensure everyting is restarted properly
+	// As part of this "planned" reboot the boot flag file is written to.
+	// If this file does not have the correct value, then a user has powered off/on the box
+	// in order to force a wakeup, so we dont want to go asleep straight away
+	// If the value is S then we have scheduled a wakeup. Anything else, or no file means manual
+	// override.
+
+	FILE *fileboot = fopen( argv[3], "r");		// Open boot flag file
+	if ( (fileboot == 0) ) {
+		printf( "Could not open boot flag file - assuming manual override\n" );
+		bootflag = "N";
+	}
+	else {
+	// read from boot state file
+	    printf( "Opened boot flag file\n");
+		    // bootflag should be "S"
+	    if (fscanf (fileboot, "%s", bootflag)) {
+		time ( &boottime );		// log time we booted			
+		fclose( fileboot );
+	    }
+	    else {
+		printf( "Error reading in from bootflag file - assuming manual restart\n" );
+		bootflag = "X";
+	    }
+	}
+
+
+// clear bootflag file - an S in this file means we are controlling the reboot (eg the user
+// did not manually turn off and on the box
+
+	fileboot = fopen( argv[3], "w");		// Open boot flag file for writing
+	if ( (fileboot == 0) ) {
+		printf( "Could not open boot flag file for writing\n" );
+	}
+	else {  // read from boot state file
+		printf( "Clearing boot flag\n");
+		fprintf(fileboot, "%s", "X");
+		fclose( fileboot );
+		}
+
+
+
+	printf ("Output to file %s\n", argv[1]);
+	printf ("Output to snapshot %s\n", argv[2]);
+	printf ("Boot flag file is %s\n", argv[3]);
+	printf ("Sleep time is %d\n", Sleep);
+	printf ("Bootflag is %s\n", bootflag);
+
+	fprintf (filelog, "\nYYYY-M-MDD,HH:MM:SS,mVolts,mAmps,Lux\n");
+
+	SNAPSHOTFILE = argv[2];
+
+	test_interfacekit(filelog, SNAPSHOTFILE, bootflag, boottime, Sleep, testVoltage);// and off we go
+        
+
+    fclose( filelog );
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sleeprtc.sh	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Expects 1 argument - time to wakeup in the format HH:MM
+
+echo "sleeprtc: Executing at `date -R`" >> /var/log/logrtc.log
+
+hourtowake=$1
+
+if [ "$1" == "" ]
+then
+    hourtowake="06:00"
+fi
+
+timenow=`date +"%H:%M"`
+
+if [ $timenow \> "22:00" ]
+then
+    timetowake=`date -d "tomorrow $hourtowake" +"%s"`
+else
+    timetowake=`date -d "$hourtowake" +"%s"`
+fi
+
+echo $timetowake
+
+
+echo "sleeprtc: Scheduling wake for local time `date -d @$timetowake`" >> /var/log/logrtc.log
+
+/usr/sbin/vbetool vbestate save > /tmp/videostate
+/usr/sbin/rtcwake -t $timetowake -m mem
+/usr/sbin/vbetool vbestate restore < /tmp/videostate
+/usr/sbin/sleep 60
+
+echo "sleeprtc: Initiating reboot after sleep at `date -R`" >> /var/log/logrtc.log
+/sbin/reboot
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stbylong.sh	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# stby180.sh
+#
+BOOTFLAGFILE=/etc/bootflag
+#
+echo "stbylong: Going asleep at `date`" >> /var/log/logrtc.log
+#
+/usr/sbin/vbetool vbestate save > /tmp/videostate
+/usr/sbin/rtcwake -s 12800 -m mem
+/usr/sbin/vbetool vbestate restore < /temp/videostate
+#
+echo "stbylong: Rebooting at `date`" >> /var/log/logrtc.log
+echo "S" > $BOOTFLAGFILE
+/sbin/reboot
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stbyshort.sh	Fri May 07 12:04:06 2010 +0100
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# stby30.sh
+#
+BOOTFLAGFILE=/etc/bootflag
+#
+echo "stbyshort: Going asleep at `date`" >> /var/log/logrtc.log
+#
+/usr/sbin/vbetool vbestate save > /tmp/videostate
+/usr/sbin/rtcwake -s 1800 -m mem
+/usr/sbin/vbetool vbestate restore < /temp/videostate
+#
+echo "stbyshort: Rebooting at `date`" >> /var/log/logrtc.log
+echo "S" > $BOOTFLAGFILE
+/sbin/reboot
+
+