|
import cPickle
|
|
import datetime
|
|
import itertools
|
|
import os
|
|
import socket
|
|
import sys
|
|
import time
|
|
|
|
import RPIO
|
|
|
|
from bfcslib.relay import Relay
|
|
from bfcslib.sensor import Sensor
|
|
from bfcslib.sensor_reading import SensorReading
|
|
from bfcslib.seven_seg import SevenSegmentDisplay
|
|
from bfcslib.status_led import LED
|
|
from bfcslib.tmp512 import TMP512
|
|
|
|
# Global variables
|
|
DEBUG = False
|
|
|
|
NUM_SENSORS = 4
|
|
sensor_iterator = itertools.cycle(range(0, NUM_SENSORS))
|
|
CURRENT_IDX = sensor_iterator.next()
|
|
SENSORS = None
|
|
|
|
THRESHOLD_TEMP = 82
|
|
|
|
HOST = '192.168.1.1'
|
|
PORT = 2243
|
|
REMOTE_DATA_INTERVAL = 1 # in seconds
|
|
|
|
def button_isr(gpio_id, val):
|
|
global CURRENT_IDX
|
|
global SENSORS
|
|
|
|
# Turn off previous sensor indicator LED
|
|
SENSORS[CURRENT_IDX].led.off()
|
|
|
|
# Update current index
|
|
# print 'CURRENT_IDX: %s' % CURRENT_IDX
|
|
CURRENT_IDX = sensor_iterator.next()
|
|
|
|
# Turn on new sensor indicator LED
|
|
SENSORS[CURRENT_IDX].led.on()
|
|
|
|
def main():
|
|
global CURRENT_IDX
|
|
global SENSORS
|
|
|
|
# Make sure the script is being run as root before continuing
|
|
if os.geteuid() != 0:
|
|
print 'ERROR: You must run the client as root!'
|
|
return
|
|
|
|
# Disable "channel already in use" warnings
|
|
RPIO.setwarnings(False)
|
|
|
|
print 'Beer Fermentation Control System - RPI Client'
|
|
|
|
# Check for the debug command line argument
|
|
if len(sys.argv) > 1:
|
|
if sys.argv[1] == '-d':
|
|
DEBUG = True
|
|
|
|
# Attempt to connect to the server, make 5 attempts
|
|
print '\n\nAttempting to connect to server...',
|
|
sys.stdout.flush()
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
tries = 5
|
|
while tries > 0:
|
|
try:
|
|
s.connect((HOST, PORT))
|
|
break
|
|
except socket.error:
|
|
tries -= 1
|
|
if tries == 0:
|
|
print 'FAILED'
|
|
print 'Unable to connect to %s:%s check your connection and ' \
|
|
'try again.' % (HOST, PORT)
|
|
return
|
|
time.sleep(1)
|
|
|
|
# Connection was successful
|
|
print 'SUCCESS'
|
|
print 'Connected to %s:%s' % (HOST, PORT)
|
|
|
|
# Setup the sensor status LEDs
|
|
sensor1_led = LED(24)
|
|
sensor2_led = LED(25)
|
|
sensor3_led = LED(8)
|
|
sensor4_led = LED(7)
|
|
|
|
# Setup both TMP512's
|
|
tmp512_1 = TMP512(0x5d)
|
|
tmp512_2 = TMP512(0x5c)
|
|
|
|
# Create the sensor objects to encapsulate a status LED and temperature
|
|
# sensor channel
|
|
sensor1 = Sensor(sensor1_led, tmp512_1.temp_sensor2)
|
|
sensor2 = Sensor(sensor2_led, tmp512_1.temp_sensor1)
|
|
sensor3 = Sensor(sensor3_led, tmp512_2.temp_sensor2)
|
|
sensor4 = Sensor(sensor4_led, tmp512_2.temp_sensor1)
|
|
|
|
# Create the global list of all the sensor objects
|
|
SENSORS = [sensor1, sensor2, sensor3, sensor4]
|
|
|
|
# Turn on initial sensor LED
|
|
SENSORS[CURRENT_IDX].led.on()
|
|
|
|
# Setup 7 seg display
|
|
ss_display = SevenSegmentDisplay()
|
|
|
|
# Setup relay
|
|
relay = Relay()
|
|
relay_state = False
|
|
|
|
# Setup pushbutton
|
|
# Use the BCM addressing scheme, set GPIO 22 as input
|
|
RPIO.setmode(RPIO.BCM)
|
|
RPIO.setup(22, RPIO.IN)
|
|
|
|
# Setup switch interrupt with debounce
|
|
RPIO.add_interrupt_callback(22, button_isr, edge='rising',
|
|
pull_up_down=RPIO.PUD_DOWN, threaded_callback=True,
|
|
debounce_timeout_ms=150)
|
|
|
|
# Wait for interrupts in a non-blocking fashion
|
|
RPIO.wait_for_interrupts(threaded=True)
|
|
|
|
# Main loop
|
|
interval_counter = 0
|
|
while True:
|
|
|
|
# Reset variables
|
|
temps = []
|
|
if interval_counter == REMOTE_DATA_INTERVAL:
|
|
interval_counter = 0
|
|
|
|
interval_counter += 1
|
|
|
|
# Grab the current date/time
|
|
now = datetime.datetime.now()
|
|
|
|
# Iterate over all temperature sensors and read their temp
|
|
for idx in xrange(NUM_SENSORS):
|
|
|
|
# Get the current temperature reading
|
|
temp = SENSORS[idx].temp
|
|
temps.append(temp)
|
|
|
|
# Display the currently selected temp sensor value
|
|
if idx == CURRENT_IDX:
|
|
ss_display.display_number(temp)
|
|
|
|
# Bit 'o debug information
|
|
if DEBUG:
|
|
print now.strftime('%m/%d/%Y %H:%M:%S')
|
|
for idx in xrange(NUM_SENSORS):
|
|
print '\t Sensor %d: %d' % (idx + 1, temps[idx])
|
|
|
|
# Sort all the temperature readings for easier manipulation
|
|
temps.sort(reverse=True)
|
|
|
|
if relay_state:
|
|
# Relay is on, decide if we need to turn it off
|
|
if temps[0] < THRESHOLD_TEMP and \
|
|
temps[1] < THRESHOLD_TEMP and \
|
|
temps[2] < THRESHOLD_TEMP and \
|
|
temps[3] < THRESHOLD_TEMP:
|
|
relay_state = False
|
|
relay.off()
|
|
else:
|
|
# Relay is off, decide if we need to turn it on
|
|
if temps[0] > THRESHOLD_TEMP and temps[1] > THRESHOLD_TEMP:
|
|
relay_state = True
|
|
relay.on()
|
|
|
|
# Send a reading to the server once every minute
|
|
if interval_counter == REMOTE_DATA_INTERVAL:
|
|
if DEBUG:
|
|
print 'Sending reading to server...',
|
|
sys.stdout.flush()
|
|
reading = SensorReading(now, temps[0], temps[1], temps[2],
|
|
temps[3], relay_state)
|
|
try:
|
|
s.sendall(cPickle.dumps(reading))
|
|
if DEBUG:
|
|
print 'DONE'
|
|
except:
|
|
if DEBUG:
|
|
print 'ERROR'
|
|
|
|
# Read once every second (approximated to account for processing
|
|
# latencies)
|
|
time.sleep(0.9)
|
|
|
|
s.close()
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|