root/software/525.743/code/rpi_client.py @ feddc602
| 856d156b | dsorber | import cPickle
|
||
| 317c2b10 | dsorber | import datetime
|
||
| e376a628 | dsorber | import itertools
|
||
| 856d156b | dsorber | import os
|
||
import socket
|
||||
| e376a628 | dsorber | import sys
|
||
| 317c2b10 | dsorber | import time
|
||
| e376a628 | dsorber | |||
import RPIO
|
||||
| 317c2b10 | dsorber | from bfcslib.relay import Relay
|
||
from bfcslib.sensor import Sensor
|
||||
| 856d156b | dsorber | from bfcslib.sensor_reading import SensorReading
|
||
| e376a628 | dsorber | from bfcslib.seven_seg import SevenSegmentDisplay
|
||
from bfcslib.status_led import LED
|
||||
from bfcslib.tmp512 import TMP512
|
||||
| 317c2b10 | dsorber | # Global variables
|
||
| abe2d7e5 | David Sorber | DEBUG = False
|
||
| e376a628 | dsorber | NUM_SENSORS = 4
|
||
sensor_iterator = itertools.cycle(range(0, NUM_SENSORS))
|
||||
CURRENT_IDX = sensor_iterator.next()
|
||||
SENSORS = None
|
||||
| 317c2b10 | dsorber | THRESHOLD_TEMP = 82
|
||
| 6ec4a106 | dsorber | HOST = '192.168.1.1'
|
||
| 856d156b | dsorber | PORT = 2243
|
||
| 6ec4a106 | dsorber | REMOTE_DATA_INTERVAL = 1 # in seconds
|
||
| 856d156b | dsorber | |||
| e376a628 | dsorber | def button_isr(gpio_id, val):
|
||
global CURRENT_IDX
|
||||
global SENSORS
|
||||
| 317c2b10 | dsorber | # Turn off previous sensor indicator LED
|
||
SENSORS[CURRENT_IDX].led.off()
|
||||
| e376a628 | dsorber | |||
# Update current index
|
||||
# print 'CURRENT_IDX: %s' % CURRENT_IDX
|
||||
CURRENT_IDX = sensor_iterator.next()
|
||||
| 317c2b10 | dsorber | # Turn on new sensor indicator LED
|
||
SENSORS[CURRENT_IDX].led.on()
|
||||
| e376a628 | dsorber | |||
def main():
|
||||
global CURRENT_IDX
|
||||
global SENSORS
|
||||
| 6e306fcd | dsorber | global DEBUG
|
||
| e376a628 | dsorber | |||
| 6ec4a106 | dsorber | # 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
|
||||
| 856d156b | dsorber | # Disable "channel already in use" warnings
|
||
RPIO.setwarnings(False)
|
||||
| e376a628 | dsorber | print 'Beer Fermentation Control System - RPI Client'
|
||
| abe2d7e5 | David Sorber | |||
# Check for the debug command line argument
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv[1] == '-d':
|
||||
DEBUG = True
|
||||
| e376a628 | dsorber | |||
| 856d156b | dsorber | # 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)
|
||||
| e376a628 | dsorber | # 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)
|
||||
| 317c2b10 | dsorber | # 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]
|
||||
| e376a628 | dsorber | |||
# Turn on initial sensor LED
|
||||
| 317c2b10 | dsorber | SENSORS[CURRENT_IDX].led.on()
|
||
| e376a628 | dsorber | |||
# Setup 7 seg display
|
||||
| 317c2b10 | dsorber | ss_display = SevenSegmentDisplay()
|
||
# Setup relay
|
||||
relay = Relay()
|
||||
relay_state = False
|
||||
| e376a628 | dsorber | |||
# Setup pushbutton
|
||||
| 317c2b10 | dsorber | # Use the BCM addressing scheme, set GPIO 22 as input
|
||
| e376a628 | dsorber | 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
|
||||
| 856d156b | dsorber | interval_counter = 0
|
||
| e376a628 | dsorber | while True:
|
||
| 856d156b | dsorber | # Reset variables
|
||
| 317c2b10 | dsorber | temps = []
|
||
| abe2d7e5 | David Sorber | if interval_counter == REMOTE_DATA_INTERVAL:
|
||
| 856d156b | dsorber | interval_counter = 0
|
||
| 317c2b10 | dsorber | |||
| 6ec4a106 | dsorber | interval_counter += 1
|
||
| 856d156b | dsorber | # Grab the current date/time
|
||
| 317c2b10 | dsorber | now = datetime.datetime.now()
|
||
| e376a628 | dsorber | # Iterate over all temperature sensors and read their temp
|
||
for idx in xrange(NUM_SENSORS):
|
||||
| 317c2b10 | dsorber | |||
# Get the current temperature reading
|
||||
temp = SENSORS[idx].temp
|
||||
temps.append(temp)
|
||||
# Display the currently selected temp sensor value
|
||||
| e376a628 | dsorber | if idx == CURRENT_IDX:
|
||
| 317c2b10 | dsorber | ss_display.display_number(temp)
|
||
# Bit 'o debug information
|
||||
| abe2d7e5 | David Sorber | 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])
|
||||
| 317c2b10 | dsorber | |||
| a7721fb9 | David Sorber | # Create the SensorReading object before we sort the temps
|
||
reading = SensorReading(now, temps[0], temps[1], temps[2],
|
||||
| 77f1c73c | David Sorber | temps[3], False)
|
||
| a7721fb9 | David Sorber | |||
| 317c2b10 | dsorber | # 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()
|
||||
| 77f1c73c | David Sorber | # Update the relay status after deciding to turn it on or off
|
||
reading.relay_status = relay_state
|
||||
| 856d156b | dsorber | # Send a reading to the server once every minute
|
||
if interval_counter == REMOTE_DATA_INTERVAL:
|
||||
| abe2d7e5 | David Sorber | if DEBUG:
|
||
print 'Sending reading to server...',
|
||||
sys.stdout.flush()
|
||||
| 856d156b | dsorber | try:
|
||
s.sendall(cPickle.dumps(reading))
|
||||
| abe2d7e5 | David Sorber | if DEBUG:
|
||
print 'DONE'
|
||||
| 856d156b | dsorber | except:
|
||
| abe2d7e5 | David Sorber | if DEBUG:
|
||
print 'ERROR'
|
||||
| 856d156b | dsorber | |||
| abe2d7e5 | David Sorber | # Read once every second (approximated to account for processing
|
||
# latencies)
|
||||
time.sleep(0.9)
|
||||
| 317c2b10 | dsorber | |||
| 856d156b | dsorber | s.close()
|
||
| 317c2b10 | dsorber | |||
| e376a628 | dsorber | if __name__ == '__main__':
|
||
| abe2d7e5 | David Sorber | sys.exit(main())
|