adding untracked files
This commit is contained in:
8
controller/config/__init__.py
Normal file
8
controller/config/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
GPIO_PIN_DHT = 4 # BCM
|
||||||
|
SENSORDATA_URL = 'http://tfm.meteor.com/api/sensorData'
|
||||||
|
GPIO_PIN_VALVE = 21 # BCM
|
||||||
|
API_BASE_URL = 'http://tfm.meteor.com/api'
|
||||||
|
CONTROLLER_ID = '120' # every controller must have a different one
|
||||||
|
STATE_FILE = '/var/run/controller_state'
|
||||||
37
controller/sensors.py
Normal file
37
controller/sensors.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import sys
|
||||||
|
import requests
|
||||||
|
import Adafruit_DHT
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
|
SENSOR_TYPE = Adafruit_DHT.DHT11
|
||||||
|
|
||||||
|
if len(sys.argv) == 3:
|
||||||
|
owner = sys.argv[1]
|
||||||
|
controller_id = sys.argv[2]
|
||||||
|
else:
|
||||||
|
print 'usage: sudo ./controller.py [OWNER] [CONTROLLER_ID]#'
|
||||||
|
print 'example: sudo ./controller.py Senad 225 - Send temperature as Senad for controller 225'
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Try to grab a sensor reading. Use the read_retry method which will retry up
|
||||||
|
# to 15 times to get a sensor reading (waiting 2 seconds between each retry).
|
||||||
|
humidity, temperature = Adafruit_DHT.read_retry(SENSOR_TYPE, GPIO_PIN_DHT)
|
||||||
|
|
||||||
|
# Un-comment the line below to convert the temperature to Fahrenheit.
|
||||||
|
# temperature = temperature * 9/5.0 + 32
|
||||||
|
|
||||||
|
# Note that sometimes you won't get a reading and
|
||||||
|
# the results will be null (because Linux can't
|
||||||
|
# guarantee the timing of calls to read the sensor).
|
||||||
|
# If this happens try again!
|
||||||
|
if temperature is not None and humidity is not None:
|
||||||
|
response = requests.post(SENSORDATA_URL, json={"owner": owner, "temperatureValue": temperature, "humidityValue":humidity})
|
||||||
|
print 'Temp={0:0.1f}*C'.format(temperature)
|
||||||
|
print 'Humidity={0:0.1f}%'.format(humidity)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print 'Failed to send temperature!'
|
||||||
|
|
||||||
|
else:
|
||||||
|
print 'Failed to get reading. Try again!'
|
||||||
19
controller/state/__init__.py
Normal file
19
controller/state/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
def sync():
|
||||||
|
server = Server(API_BASE_URL, CONTROLLER_ID)
|
||||||
|
local = File(STATE_FILE)
|
||||||
|
server_state = server.get_state()
|
||||||
|
|
||||||
|
if local.present():
|
||||||
|
local.load()
|
||||||
|
else:
|
||||||
|
local.data = server_state
|
||||||
|
local.save()
|
||||||
|
|
||||||
|
local_state = local.data
|
||||||
|
|
||||||
|
changer = Changer(local_state, remote_state)
|
||||||
|
current_state = changer.process_change()
|
||||||
|
|
||||||
|
server.post_state(current_state)
|
||||||
39
controller/state/changer.py
Normal file
39
controller/state/changer.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import config
|
||||||
|
|
||||||
|
class Changer(object):
|
||||||
|
|
||||||
|
def __init__(self, local_state, remote_state):
|
||||||
|
self.local_state = local_state
|
||||||
|
self.remote_state = remote_state
|
||||||
|
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
|
||||||
|
GPIO.setup(GPIO_PIN_VALVE, GPIO.OUT)
|
||||||
|
|
||||||
|
self.states = {
|
||||||
|
'opening': self.open_valve,
|
||||||
|
'closing': self.close_valve,
|
||||||
|
'open': self.open_valve,
|
||||||
|
'closed': self.close_valve
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def process_change(self):
|
||||||
|
self.validate_states()
|
||||||
|
if self.local_state['out_valve'] != self.remote_state['out_valve']:
|
||||||
|
change = self.states.get(self.remote_state['out_valve'], None )
|
||||||
|
if change is not None:
|
||||||
|
change()
|
||||||
|
return self.local_state
|
||||||
|
|
||||||
|
def open_valve():
|
||||||
|
GPIO.output(GPIO_PIN_VALVE, GPIO.HIGH)
|
||||||
|
self.local_state['out_valve'] = 'open'
|
||||||
|
|
||||||
|
def close_valve():
|
||||||
|
GPIO.output(GPIO_PIN_VALVE, GPIO.LOW)
|
||||||
|
self.local_state['out_valve'] = 'closed'
|
||||||
|
|
||||||
|
def validate_states(self):
|
||||||
|
if self.local_state is None or self.remote_state is None:
|
||||||
|
raise ClassNotReadyException("Both local and remote states must be present!")
|
||||||
|
# TODO: add detailed validation
|
||||||
14
controller/state/exceptions.py
Normal file
14
controller/state/exceptions.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
class ClassNotReadyException(Exception):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
class ErrorCommunicatingWithServerException(Exception):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
27
controller/state/file.py
Normal file
27
controller/state/file.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class File(object):
|
||||||
|
"Holds controller state in the file"
|
||||||
|
def __init__(self, filename=None):
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
def present(self):
|
||||||
|
os.path.isfile(self.filename)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
if self.filename is None:
|
||||||
|
raise ClassNotReadyException("Filename not set!")
|
||||||
|
with open(self.filename) as input_file:
|
||||||
|
self.data = json.load(input_file)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
if self.filename is None:
|
||||||
|
raise ClassNotReadyException("Filename not set!")
|
||||||
|
if self.data is None:
|
||||||
|
raise ClassNotReadyException("Data not loaded!")
|
||||||
|
|
||||||
|
with open(self.filename, 'w') as out_file:
|
||||||
|
json.dump(self.data, out_file)
|
||||||
33
controller/state/server.py
Normal file
33
controller/state/server.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class Server(object):
|
||||||
|
"Gets state from server and sends it to the server after change"
|
||||||
|
def __init__(self, url_base=None, controller_id=None):
|
||||||
|
self.url_base = url_base
|
||||||
|
self.controller_id = controller_id
|
||||||
|
|
||||||
|
def get_state(self):
|
||||||
|
result = requests.get(self.full_url('state/%s') % self.controller_id)
|
||||||
|
return handle_response(result)
|
||||||
|
|
||||||
|
def post_state(self, local_state):
|
||||||
|
result = requests.post(self.full_url('state/%s') % self.controller_id, local_state)
|
||||||
|
return handle_response(result)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def full_url(self, action):
|
||||||
|
if self.controller_id is None:
|
||||||
|
raise ClassNotReadyException("Controller id not set!")
|
||||||
|
if self.url_base is None:
|
||||||
|
raise ClassNotReadyException("URL base not set!")
|
||||||
|
return self.url_base + '/' + action
|
||||||
|
|
||||||
|
|
||||||
|
def handle_response(response):
|
||||||
|
if response.status_code != 200:
|
||||||
|
raise ErrorCommunicatingWithServerException("Response not 200!")
|
||||||
|
else:
|
||||||
|
return response.json()
|
||||||
3
controller/sync_state.py
Normal file
3
controller/sync_state.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import state
|
||||||
|
|
||||||
|
state.sync()
|
||||||
Reference in New Issue
Block a user