dweet fix again
This commit is contained in:
39
app/controller/state/__init__.py
Normal file
39
app/controller/state/__init__.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import config
|
||||
from state.server import Server
|
||||
from state.changer import Changer
|
||||
from state.file import File
|
||||
import commands
|
||||
|
||||
def safely_panic():
|
||||
safe_state = {}
|
||||
changer = Changer(safe_state,safe_state)
|
||||
changer.stop_everything()
|
||||
|
||||
|
||||
def sync():
|
||||
try:
|
||||
server = Server(config.API_BASE_URL, config.CONTROLLER_ID)
|
||||
local = File(config.STATE_FILE)
|
||||
server_state = server.get_state()
|
||||
|
||||
if local.present():
|
||||
local.load()
|
||||
print "local present: " + repr(local.data)
|
||||
else:
|
||||
local.data = server_state
|
||||
print "local not present, server: " + repr(local.data)
|
||||
local.save()
|
||||
|
||||
local_state = local.data
|
||||
|
||||
changer = Changer(local_state, server_state)
|
||||
current_state = changer.process_change()
|
||||
|
||||
server.post_state(current_state)
|
||||
print " everything ok, canceling shutdown "
|
||||
commands.getoutput('/sbin/shutdown -c')
|
||||
except:
|
||||
print " panicking safely ! "
|
||||
safely_panic()
|
||||
print " rebooting "
|
||||
commands.getoutput('/sbin/shutdown -r +3')
|
||||
69
app/controller/state/changer.py
Normal file
69
app/controller/state/changer.py
Normal file
@@ -0,0 +1,69 @@
|
||||
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(config.GPIO_PIN_OUT_VALVE, GPIO.OUT)
|
||||
GPIO.setup(config.GPIO_PIN_IN_VALVE, GPIO.OUT)
|
||||
|
||||
self.out_valve_states = {
|
||||
'opening': self.open_out_valve,
|
||||
'closing': self.close_out_valve,
|
||||
'open': self.open_out_valve,
|
||||
'closed': self.close_out_valve
|
||||
}
|
||||
|
||||
self.in_valve_states = {
|
||||
'opening': self.open_in_valve,
|
||||
'closing': self.close_in_valve,
|
||||
'open': self.open_in_valve,
|
||||
'closed': self.close_in_valve
|
||||
}
|
||||
|
||||
def stop_everything(self):
|
||||
self.close_in_valve()
|
||||
self.close_out_valve()
|
||||
|
||||
def safe_remote_state(self, key):
|
||||
if key in ['out_valve', 'in_valve']:
|
||||
return self.remote_state.get(key, 'closed')
|
||||
else:
|
||||
return self.remote_state.get(key,'');
|
||||
|
||||
def process_change(self):
|
||||
self.validate_states()
|
||||
|
||||
out_valve_change = self.out_valve_states.get(self.safe_remote_state('out_valve'), None )
|
||||
if out_valve_change is not None:
|
||||
out_valve_change()
|
||||
|
||||
in_valve_change = self.in_valve_states.get(self.safe_remote_state('in_valve'), None )
|
||||
if in_valve_change is not None:
|
||||
in_valve_change()
|
||||
|
||||
return self.local_state
|
||||
|
||||
def open_in_valve(self):
|
||||
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.HIGH)
|
||||
self.local_state['in_valve'] = 'open'
|
||||
|
||||
def close_in_valve(self):
|
||||
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.LOW)
|
||||
self.local_state['in_valve'] = 'closed'
|
||||
|
||||
def open_out_valve(self):
|
||||
GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.HIGH)
|
||||
self.local_state['out_valve'] = 'open'
|
||||
|
||||
def close_out_valve(self):
|
||||
GPIO.output(config.GPIO_PIN_OUT_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
|
||||
33
app/controller/state/dweet_server.py
Normal file
33
app/controller/state/dweet_server.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import json
|
||||
import requests
|
||||
|
||||
|
||||
DWEET_UID = "5410ab1e-319c-4f14-a2e4-04725df69121"
|
||||
|
||||
class DweetServer(object):
|
||||
"Gets state from server and sends it to the server after change"
|
||||
def __init__(self, controller_id=None):
|
||||
self.url_base = "https://dweet.io:443/dweet/quietly/for/%s" % DWEET_UID
|
||||
self.controller_id = controller_id
|
||||
|
||||
def send_message(self, message):
|
||||
result = requests.post(self.full_url(),
|
||||
json=json.dumps({
|
||||
'controller_id': self.controller_id,
|
||||
'message': message
|
||||
}))
|
||||
return handle_response(result)
|
||||
|
||||
def full_url(self):
|
||||
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
|
||||
|
||||
|
||||
def handle_response(response):
|
||||
if response.status_code != 200 or response.status_code != 204:
|
||||
raise Exception("Response not 200 or 204!")
|
||||
else:
|
||||
return response.json()
|
||||
14
app/controller/state/exceptions.py
Normal file
14
app/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
app/controller/state/file.py
Normal file
27
app/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)
|
||||
31
app/controller/state/server.py
Normal file
31
app/controller/state/server.py
Normal file
@@ -0,0 +1,31 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user