Sorted include files.

Checks for missing config.json and discovery.json.
Fixed string constants.

NOTRY=true

Review URL: https://codereview.chromium.org/293833003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271521 0039d316-1c4b-4281-b951-d872f2087c98
parent 1fd97c22
...@@ -6,64 +6,65 @@ ...@@ -6,64 +6,65 @@
# This prototype has tons of flaws, not the least of which being that it # This prototype has tons of flaws, not the least of which being that it
# occasionally will block while waiting for commands to finish. However, this is # occasionally will block while waiting for commands to finish. However, this is
# a quick sketch. # a quick sketch.
# Script requires following components:
# sudo apt-get install python-tornado
# sudo apt-get install python-pip
# sudo pip install google-api-python-client
import subprocess
import json
import tornado.httpserver
import tornado.ioloop
import time
import atexit import atexit
import apiclient.errors import base64
from apiclient.discovery import build_from_document
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
import oauth2client.client
import datetime import datetime
import httplib2 import httplib2
import json
import os import os
import subprocess
import time
import traceback import traceback
import urlparse
import base64 from apiclient.discovery import build_from_document
from apiclient.errors import HttpError
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
_OAUTH_SCOPE = 'https://www.googleapis.com/auth/clouddevices' _OAUTH_SCOPE = 'https://www.googleapis.com/auth/clouddevices'
_API_CLIENT_FILE = 'config.json'
_API_DISCOVERY_FILE = 'discovery.json'
DEVICE_DRAFT = { DEVICE_DRAFT = {
"systemName": "LEDFlasher", 'systemName': 'LEDFlasher',
"deviceKind": "vendor", 'deviceKind': 'vendor',
"displayName": "LED Flasher", 'displayName': 'LED Flasher',
"channel": 'channel': {
{ 'supportedType': 'xmpp'
"supportedType": "xmpp"
}, },
"commands": 'commands': {
{ 'base': {
"base": 'vendorCommands': [{
{ 'name': 'flashLED',
"vendorCommands": 'parameter' : [{
[ 'name': 'times',
{ 'type': 'string'
"name": "flashLED", }]
"parameter" : [{
"name": "times",
"type": "string"
}] }]
}
]
}
} }
} }
}
wpa_supplicant_cmd = "wpa_supplicant -Dwext -iwlan0 -cwpa_supplicant.conf" wpa_supplicant_cmd = 'wpa_supplicant -Dwext -iwlan0 -cwpa_supplicant.conf'
ifconfig_cmd = "ifconfig wlan0 192.168.0.3" ifconfig_cmd = 'ifconfig wlan0 192.168.0.3'
hostapd_cmd = "hostapd hostapd-min.conf" hostapd_cmd = 'hostapd hostapd-min.conf'
dhclient_release = "dhclient -r wlan0" dhclient_release = 'dhclient -r wlan0'
dhclient_renew = "dhclient wlan0" dhclient_renew = 'dhclient wlan0'
dhcpd_cmd = "udhcpd -f /etc/udhcpd.conf" dhcpd_cmd = 'udhcpd -f /etc/udhcpd.conf'
wpa_supplicant_conf = "wpa_supplicant.conf" wpa_supplicant_conf = 'wpa_supplicant.conf'
wpa_supplicant_template = """network={ wpa_supplicant_template = """
network={
ssid="%s" ssid="%s"
scan_ssid=1 scan_ssid=1
proto=WPA RSN proto=WPA RSN
...@@ -73,7 +74,7 @@ wpa_supplicant_template = """network={ ...@@ -73,7 +74,7 @@ wpa_supplicant_template = """network={
psk="%s" psk="%s"
}""" }"""
led_path = "/sys/class/leds/ath9k_htc-phy0/" led_path = '/sys/class/leds/ath9k_htc-phy0/'
class DeviceUnregisteredError(Exception): class DeviceUnregisteredError(Exception):
pass pass
...@@ -83,7 +84,7 @@ def ignore_errors(func): ...@@ -83,7 +84,7 @@ def ignore_errors(func):
try: try:
func(*args, **kwargs) func(*args, **kwargs)
except: except:
print "Got error in unsafe function:" print 'Got error in unsafe function:'
traceback.print_exc() traceback.print_exc()
return inner return inner
...@@ -107,31 +108,31 @@ class CommandWrapperFake(object): ...@@ -107,31 +108,31 @@ class CommandWrapperFake(object):
def __init__(self, cmd): def __init__(self, cmd):
self.cmd = cmd self.cmd = cmd
def start(self): def start(self):
print "Start: ", self.cmd print 'Start: ', self.cmd
def wait(self): def wait(self):
print "Wait: ", self.cmd print 'Wait: ', self.cmd
def end(self): def end(self):
print "End: ", self.cmd print 'End: ', self.cmd
class CloudCommandHandlerFake(object): class CloudCommandHandlerFake(object):
def __init__(self, ioloop): def __init__(self, ioloop):
pass pass
def handle_command(self, command_name, args): def handle_command(self, command_name, args):
if command_name == "flashLED": if command_name == 'flashLED':
times = 1 times = 1
if "times" in args: if 'times' in args:
times = int(args["times"]) times = int(args['times'])
print "Flashing LED %d times" % times print 'Flashing LED %d times' % times
class CloudCommandHandlerReal(object): class CloudCommandHandlerReal(object):
def __init__(self, ioloop): def __init__(self, ioloop):
self.ioloop = ioloop self.ioloop = ioloop
def handle_command(self, command_name, args): def handle_command(self, command_name, args):
if command_name == "flashLED": if command_name == 'flashLED':
times = 1 times = 1
if "times" in args: if 'times' in args:
times = int(args["times"]) times = int(args['times'])
print "Really flashing LED %d times" % times print 'Really flashing LED %d times' % times
self.flash_led(times) self.flash_led(times)
@ignore_errors @ignore_errors
def flash_led(self, times): def flash_led(self, times):
...@@ -140,12 +141,12 @@ class CloudCommandHandlerReal(object): ...@@ -140,12 +141,12 @@ class CloudCommandHandlerReal(object):
if not times: if not times:
return return
file_trigger = open(os.path.join(led_path, "brightness"), "w") file_trigger = open(os.path.join(led_path, 'brightness'), 'w')
if value: if value:
file_trigger.write("1") file_trigger.write('1')
else: else:
file_trigger.write("0") file_trigger.write('0')
file_trigger.close() file_trigger.close()
...@@ -156,16 +157,16 @@ class WifiHandler(object): ...@@ -156,16 +157,16 @@ class WifiHandler(object):
class Delegate: class Delegate:
# Token is optional, and all delegates should support it being None # Token is optional, and all delegates should support it being None
def on_wifi_connected(self, token): def on_wifi_connected(self, token):
raise Exception("Unhandled condition: WiFi connected") raise Exception('Unhandled condition: WiFi connected')
def __init__(self, ioloop, state, delegate): def __init__(self, ioloop, state, delegate):
self.ioloop = ioloop self.ioloop = ioloop
self.state = state self.state = state
self.delegate = delegate self.delegate = delegate
def start(self): def start(self):
raise Exception("Start not implemented!") raise Exception('Start not implemented!')
def get_ssid(self): def get_ssid(self):
raise Exception("Get SSID not implemented!") raise Exception('Get SSID not implemented!')
# Note that by using CommandWrapperFake, you can run WifiHandlerReal on fake # Note that by using CommandWrapperFake, you can run WifiHandlerReal on fake
# devices for testing the wifi-specific logic # devices for testing the wifi-specific logic
...@@ -190,7 +191,7 @@ class WifiHandlerReal(WifiHandler): ...@@ -190,7 +191,7 @@ class WifiHandlerReal(WifiHandler):
self.dhcpd.start() self.dhcpd.start()
def switch_to_wifi(self, ssid, passwd, token): def switch_to_wifi(self, ssid, passwd, token):
try: try:
wpa_config = open(wpa_supplicant_conf, "w") wpa_config = open(wpa_supplicant_conf, 'w')
wpa_config.write(wpa_supplicant_template % (ssid, passwd)) wpa_config.write(wpa_supplicant_template % (ssid, passwd))
wpa_config.close() wpa_config.close()
self.hostapd.end() self.hostapd.end()
...@@ -219,20 +220,20 @@ class WifiHandlerPassthrough(WifiHandler): ...@@ -219,20 +220,20 @@ class WifiHandlerPassthrough(WifiHandler):
def start(self): def start(self):
self.delegate.on_wifi_connected(None) self.delegate.on_wifi_connected(None)
def switch_to_wifi(self, ssid, passwd, token): def switch_to_wifi(self, ssid, passwd, token):
raise Exception("Should not be reached") raise Exception('Should not be reached')
def get_ssid(self): def get_ssid(self):
return "dummy" return 'dummy'
def setup_fake(): def setup_fake():
print "Called setup" print 'Called setup'
def setup_real(): def setup_real():
file_trigger = open(os.path.join(led_path, "trigger"), "w") file_trigger = open(os.path.join(led_path, 'trigger'), 'w')
file_trigger.write("none") file_trigger.write('none')
file_trigger.close() file_trigger.close()
if os.path.exists("on_real_device"): if os.path.exists('on_real_device'):
CommandWrapper = CommandWrapperReal CommandWrapper = CommandWrapperReal
CommandWrapperMDns = CommandWrapperReal CommandWrapperMDns = CommandWrapperReal
CloudCommandHandler = CloudCommandHandlerReal CloudCommandHandler = CloudCommandHandlerReal
...@@ -253,36 +254,36 @@ class State: ...@@ -253,36 +254,36 @@ class State:
self.credentials_ = None self.credentials_ = None
self.has_credentials_ = False self.has_credentials_ = False
self.has_wifi_ = False self.has_wifi_ = False
self.ssid_ = "" self.ssid_ = ''
self.password_ = "" self.password_ = ''
self.device_id_ = "" self.device_id_ = ''
def reset(self): def reset(self):
self.clear() self.clear()
self.dump() self.dump()
def dump(self): def dump(self):
json_obj = { json_obj = {
"has_credentials": self.has_credentials_, 'has_credentials': self.has_credentials_,
"has_wifi": self.has_wifi_, 'has_wifi': self.has_wifi_,
"ssid": self.ssid_, 'ssid': self.ssid_,
"password": self.password_, 'password': self.password_,
"device_id": self.device_id_ } 'device_id': self.device_id_ }
statefile = open("device_state.json", "w") statefile = open('device_state.json', 'w')
json.dump(json_obj, statefile) json.dump(json_obj, statefile)
statefile.close() statefile.close()
if self.has_credentials_: if self.has_credentials_:
self.oauth_storage_.put(self.credentials_) self.oauth_storage_.put(self.credentials_)
def load(self): def load(self):
if os.path.exists("device_state.json"): if os.path.exists('device_state.json'):
statefile = open("device_state.json", "r") statefile = open('device_state.json', 'r')
json_obj = json.load(statefile) json_obj = json.load(statefile)
statefile.close() statefile.close()
self.has_credentials_ = json_obj["has_credentials"] self.has_credentials_ = json_obj['has_credentials']
self.has_wifi_ = json_obj["has_wifi"] self.has_wifi_ = json_obj['has_wifi']
self.ssid_ = json_obj["ssid"] self.ssid_ = json_obj['ssid']
self.password_ = json_obj["password"] self.password_ = json_obj['password']
self.device_id_ = json_obj["device_id"] self.device_id_ = json_obj['device_id']
if self.has_credentials_: if self.has_credentials_:
self.credentials_ = self.oauth_storage_.get() self.credentials_ = self.oauth_storage_.get()
...@@ -318,17 +319,17 @@ class MDnsWrapper: ...@@ -318,17 +319,17 @@ class MDnsWrapper:
def __init__(self): def __init__(self):
self.avahi_wrapper = None self.avahi_wrapper = None
self.setup_name = None self.setup_name = None
self.device_id = "" self.device_id = ''
self.started = False self.started = False
def start(self): def start(self):
self.started = True self.started = True
self.run_command() self.run_command()
def get_command(self): def get_command(self):
cmd = ["avahi-publish", "-s", "Raspberry Pi" , "_privet._tcp", "8080", cmd = ['avahi-publish', '-s', 'Raspberry Pi' , '_privet._tcp', '8080',
"txtvers=2", "type=wifi", "ty=Raspberry Pi", 'txtvers=2', 'type=wifi', 'ty=Raspberry Pi',
"id=" + self.device_id] 'id=' + self.device_id]
if self.setup_name: if self.setup_name:
cmd.append("setup=" + self.setup_name) cmd.append('setup=' + self.setup_name)
return cmd return cmd
def run_command(self): def run_command(self):
if self.avahi_wrapper: if self.avahi_wrapper:
...@@ -349,22 +350,36 @@ class MDnsWrapper: ...@@ -349,22 +350,36 @@ class MDnsWrapper:
class CloudDevice: class CloudDevice:
class Delegate: class Delegate:
def on_device_started(self): def on_device_started(self):
raise Exception("Not implemented: Device started") raise Exception('Not implemented: Device started')
def on_device_stopped(self): def on_device_stopped(self):
raise Exception("Not implemented: Device stopped") raise Exception('Not implemented: Device stopped')
def __init__(self, ioloop, state, delegate): def __init__(self, ioloop, state, delegate):
self.state = state self.state = state
self.http = httplib2.Http() self.http = httplib2.Http()
if not os.path.isfile(_API_CLIENT_FILE):
credentials = {
'oauth_client_id' : '',
'oauth_secret' : '',
'api_key' : ''
}
credentials_f = open(_API_CLIENT_FILE + '.samlpe', 'w')
credentials_f.write(json.dumps(credentials));
credentials_f.close()
raise Exception('Missing ' + _API_CLIENT_FILE);
credentials_f = open("api_client.json") credentials_f = open(_API_CLIENT_FILE)
credentials = json.load(credentials_f) credentials = json.load(credentials_f)
credentials_f.close() credentials_f.close()
self.oauth_client_id = credentials["oauth_client_id"] self.oauth_client_id = credentials['oauth_client_id']
self.oauth_secret = credentials["oauth_secret"] self.oauth_secret = credentials['oauth_secret']
self.api_key = credentials["api_key"] self.api_key = credentials['api_key']
if not os.path.isfile(_API_DISCOVERY_FILE):
raise Exception('Download https://developers.google.com/'
'cloud-devices/v1/discovery.json');
f = open("clouddevices.json") f = open('discovery.json')
discovery = f.read() discovery = f.read()
f.close() f.close()
self.gcd = build_from_document( self.gcd = build_from_document(
...@@ -384,8 +399,8 @@ class CloudDevice: ...@@ -384,8 +399,8 @@ class CloudDevice:
elif token: elif token:
self.register(token) self.register(token)
else: else:
print "Device not registered and has no credentials." print 'Device not registered and has no credentials.'
print "Waiting for registration." print 'Waiting for registration.'
def register(self, token): def register(self, token):
resource = { resource = {
'deviceDraft': DEVICE_DRAFT, 'deviceDraft': DEVICE_DRAFT,
...@@ -405,7 +420,7 @@ class CloudDevice: ...@@ -405,7 +420,7 @@ class CloudDevice:
self.credentials = flow.step2_exchange(authorization_code) self.credentials = flow.step2_exchange(authorization_code)
self.device_id = finalTicket['deviceDraft']['id'] self.device_id = finalTicket['deviceDraft']['id']
self.state.set_credentials(self.credentials, self.device_id) self.state.set_credentials(self.credentials, self.device_id)
print "Registered with device_id ", self.device_id print 'Registered with device_id ', self.device_id
self.run_device() self.run_device()
def run_device(self): def run_device(self):
...@@ -413,11 +428,11 @@ class CloudDevice: ...@@ -413,11 +428,11 @@ class CloudDevice:
try: try:
dev=self.gcd.devices().get(deviceId=self.device_id).execute() dev=self.gcd.devices().get(deviceId=self.device_id).execute()
except apiclient.errors.HttpError, e: except HttpError, e:
# Pretty good indication the device was deleted # Pretty good indication the device was deleted
if e.resp.status == 404: if e.resp.status == 404:
raise DeviceUnregisteredError() raise DeviceUnregisteredError()
except oauth2client.client.AccessTokenRefreshError: except AccessTokenRefreshError:
raise DeviceUnregisteredError() raise DeviceUnregisteredError()
self.check_commands() self.check_commands()
...@@ -426,29 +441,29 @@ class CloudDevice: ...@@ -426,29 +441,29 @@ class CloudDevice:
if not self.active: if not self.active:
return return
print "Checking commands..." print 'Checking commands...'
commands = self.gcd.commands().list(deviceId=self.device_id, commands = self.gcd.commands().list(deviceId=self.device_id,
state="queued").execute() state='queued').execute()
if "commands" in commands: if 'commands' in commands:
print "Found ", len(commands["commands"]), " commands" print 'Found ', len(commands['commands']), ' commands'
args = {} args = {}
vendorCommandName = None vendorCommandName = None
for command in commands["commands"]: for command in commands['commands']:
try: try:
if command["name"].startswith("base._"): if command['name'].startswith('base._'):
vendorCommandName = command["name"][ vendorCommandName = command['name'][
len("base._"):] len('base._'):]
if "parameters" in command: if 'parameters' in command:
parameters = command["parameters"] parameters = command['parameters']
else: else:
parameters = {} parameters = {}
else: else:
vendorCommandName = None vendorCommandName = None
except KeyError: except KeyError:
print "Could not parse vendor command ", print 'Could not parse vendor command ',
print repr(command) print repr(command)
vendorCommandName = None vendorCommandName = None
...@@ -457,10 +472,10 @@ class CloudDevice: ...@@ -457,10 +472,10 @@ class CloudDevice:
vendorCommandName, vendorCommandName,
parameters) parameters)
self.gcd.commands().patch(commandId = command["id"], self.gcd.commands().patch(commandId = command['id'],
body={"state": "done"}).execute() body={'state': 'done'}).execute()
else: else:
print "Found no commands" print 'Found no commands'
self.ioloop.add_timeout(datetime.timedelta(milliseconds=1000), self.ioloop.add_timeout(datetime.timedelta(milliseconds=1000),
self.check_commands) self.check_commands)
...@@ -471,14 +486,14 @@ class CloudDevice: ...@@ -471,14 +486,14 @@ class CloudDevice:
def get_only(f): def get_only(f):
def inner(self, request, response_func, *args): def inner(self, request, response_func, *args):
if request.method != "GET": if request.method != 'GET':
return False return False
return f(self, request, response_func, *args) return f(self, request, response_func, *args)
return inner return inner
def post_only(f): def post_only(f):
def inner(self, request, response_func, *args): def inner(self, request, response_func, *args):
if request.method != "POST": if request.method != 'POST':
return False return False
return f(self, request, response_func, *args) return f(self, request, response_func, *args)
return inner return inner
...@@ -500,15 +515,15 @@ def post_provisioning(f): ...@@ -500,15 +515,15 @@ def post_provisioning(f):
def extract_encryption_params(f): def extract_encryption_params(f):
def inner(self, request, response_func, *args): def inner(self, request, response_func, *args):
try: try:
client_id = request.headers["X-Privet-Client-ID"] client_id = request.headers['X-Privet-Client-ID']
if "X-Privet-Encrypted" in request.headers: if 'X-Privet-Encrypted' in request.headers:
encrypted = (request.headers["X-Privet-Encrypted"].lower() encrypted = (request.headers['X-Privet-Encrypted'].lower()
== "true") == 'true')
else: else:
encrypted = False encrypted = False
except (KeyError, TypeError): except (KeyError, TypeError):
print "Missing client parameters in headers" print 'Missing client parameters in headers'
response_func(400, { "error": "missing_client_parameters" }) response_func(400, { 'error': 'missing_client_parameters' })
return True return True
return f(self, request, response_func, client_id, encrypted, *args) return f(self, request, response_func, client_id, encrypted, *args)
...@@ -560,7 +575,7 @@ class DummySession: ...@@ -560,7 +575,7 @@ class DummySession:
def get_client_id(self): def get_client_id(self):
return client_id return client_id
def get_stype(self): def get_stype(self):
return "dummy" return 'dummy'
class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
def __init__(self, ioloop, state): def __init__(self, ioloop, state):
...@@ -572,15 +587,15 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -572,15 +587,15 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
self.in_session = False self.in_session = False
self.ioloop = ioloop self.ioloop = ioloop
self.handlers = { self.handlers = {
"/internal/ping": self.do_ping, '/internal/ping': self.do_ping,
"/privet/info": self.do_info, '/privet/info': self.do_info,
"/deprecated/wifi/switch": self.do_wifi_switch, '/deprecated/wifi/switch': self.do_wifi_switch,
"/privet/v2/session/handshake": self.do_session_handshake, '/privet/v2/session/handshake': self.do_session_handshake,
"/privet/v2/session/cancel": self.do_session_cancel, '/privet/v2/session/cancel': self.do_session_cancel,
"/privet/v2/session/api": self.do_session_api, '/privet/v2/session/api': self.do_session_api,
"/privet/v2/setup/start": self.get_insecure_api_handler( '/privet/v2/setup/start': self.get_insecure_api_handler(
self.do_secure_setup), self.do_secure_setup),
"/privet/v2/setup/status": self.get_insecure_api_handler( '/privet/v2/setup/status': self.get_insecure_api_handler(
self.do_secure_status), self.do_secure_status),
} }
...@@ -588,27 +603,27 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -588,27 +603,27 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
self.current_session = None self.current_session = None
self.session_cancel_callback = None self.session_cancel_callback = None
self.session_handlers = { self.session_handlers = {
"dummy" : DummySession 'dummy' : DummySession
} }
self.secure_handlers = { self.secure_handlers = {
"/privet/v2/setup/start" : self.do_secure_setup, '/privet/v2/setup/start' : self.do_secure_setup,
"/privet/v2/setup/status" : self.do_secure_status '/privet/v2/setup/status' : self.do_secure_status
} }
def start(self): def start(self):
self.wifi_handler.start() self.wifi_handler.start()
self.mdns_wrapper.set_setup_name("RaspberryPi.camera.privet") self.mdns_wrapper.set_setup_name('RaspberryPi.camera.privet')
self.mdns_wrapper.start() self.mdns_wrapper.start()
@get_only @get_only
def do_ping(self, request, response_func): def do_ping(self, request, response_func):
response_func(200, "{ \"pong\": true }") response_func(200, '{ "pong": true }')
return True return True
@get_only @get_only
def do_public_info(self, request, response_func): def do_public_info(self, request, response_func):
info = merge_dictionary( info = merge_dictionary(
self.get_common_info(), self.get_common_info(),
{ {
"stype" : self.session_handlers.keys() 'stype' : self.session_handlers.keys()
}) })
self.real_send_response( self.real_send_response(
...@@ -617,7 +632,7 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -617,7 +632,7 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
@get_only @get_only
def do_info(self, request, response_func): def do_info(self, request, response_func):
specific_info = { specific_info = {
"x-privet-token": "sample", 'x-privet-token': 'sample',
} }
info = merge_dictionary( info = merge_dictionary(
...@@ -632,16 +647,16 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -632,16 +647,16 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
def do_wifi_switch(self, request, response_func): def do_wifi_switch(self, request, response_func):
data = json.loads(request.body) data = json.loads(request.body)
try: try:
ssid = data["ssid"] ssid = data['ssid']
passw = data["passw"] passw = data['passw']
except KeyError: except KeyError:
print "Malformed content: " + repr(data) print 'Malformed content: ' + repr(data)
self.real_send_response( self.real_send_response(
request, 400, { "error": "invalid_params" }) request, 400, { 'error': 'invalid_params' })
traceback.print_exc() traceback.print_exc()
return True return True
response_func(200, { "ssid": ssid } ) response_func(200, { 'ssid': ssid } )
self.wifi_handler.switch_to_wifi(ssid, passw, None) self.wifi_handler.switch_to_wifi(ssid, passw, None)
# TODO: Return to normal wifi after timeout (cancelable) # TODO: Return to normal wifi after timeout (cancelable)
return True return True
...@@ -652,29 +667,29 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -652,29 +667,29 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
encrypted): encrypted):
data = json.loads(request.body) data = json.loads(request.body)
try: try:
stype = data["stype"] stype = data['stype']
step = data["step"] step = data['step']
package = base64.b64decode(data["package"]) package = base64.b64decode(data['package'])
except (KeyError, TypeError): except (KeyError, TypeError):
traceback.print_exc() traceback.print_exc()
print "Malformed content: " + repr(data) print 'Malformed content: ' + repr(data)
self.real_send_response( self.real_send_response(
request, 400, { "error": "invalid_params" }) request, 400, { 'error': 'invalid_params' })
return True return True
if self.current_session: if self.current_session:
if client_id != self.current_session.get_client_id(): if client_id != self.current_session.get_client_id():
self.real_send_response( self.real_send_response(
request, 500, { "error": "in_session" }) request, 500, { 'error': 'in_session' })
return True return True
if stype != self.current_session.get_stype(): if stype != self.current_session.get_stype():
self.real_send_response( self.real_send_response(
request, 500, { "error": "invalid_stype" }) request, 500, { 'error': 'invalid_stype' })
return True return True
else: else:
if stype not in self.session_handlers: if stype not in self.session_handlers:
self.real_send_response( self.real_send_response(
request, 500, { "error": "invalid_stype" }) request, 500, { 'error': 'invalid_stype' })
return True return True
self.current_session = self.session_handlers[stype](client_id) self.current_session = self.session_handlers[stype](client_id)
...@@ -682,17 +697,17 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -682,17 +697,17 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
output_package = self.current_session.do_step(step, package) output_package = self.current_session.do_step(step, package)
except InvalidStepError: except InvalidStepError:
self.real_send_response( self.real_send_response(
request, 500, { "error": "invalid_step" }) request, 500, { 'error': 'invalid_step' })
return True return True
except InvalidPackageError: except InvalidPackageError:
self.real_send_response( self.real_send_response(
request, 500, { "error": "invalid_step" }) request, 500, { 'error': 'invalid_step' })
return True return True
return_obj = { return_obj = {
"stype" : stype, 'stype' : stype,
"step" : step, 'step' : step,
"package": base64.b64encode(output_package)} 'package': base64.b64encode(output_package)}
self.real_send_response( self.real_send_response(
request, 200, json.dumps(return_obj)) request, 200, json.dumps(return_obj))
...@@ -710,48 +725,48 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -710,48 +725,48 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
self.session_cancel_callback.cancel() self.session_cancel_callback.cancel()
else: else:
self.real_send_response( self.real_send_response(
request, 400, { "error": "invalid_client_id" }) request, 400, { 'error': 'invalid_client_id' })
return True return True
@extract_encryption_params @extract_encryption_params
@post_only @post_only
@wifi_provisioning @wifi_provisioning
def do_session_api(self, request, response_func, client_id, encrypted): def do_session_api(self, request, response_func, client_id, encrypted):
if not encrypted: if not encrypted:
response_func(400, { "error": "encryption_required" }) response_func(400, { 'error': 'encryption_required' })
return True return True
if (not self.current_session or if (not self.current_session or
client_id != self.current_session.client_id): client_id != self.current_session.client_id):
response_func(405, { "error": "invalid_client_id" }) response_func(405, { 'error': 'invalid_client_id' })
return True return True
try: try:
decrypted = self.current_session.decrypt(request.body) decrypted = self.current_session.decrypt(request.body)
except EncryptionError: except EncryptionError:
response_func(415, { "error": "decryption_failed" }) response_func(415, { 'error': 'decryption_failed' })
return True return True
def encrypted_response_func(code, data): def encrypted_response_func(code, data):
if "error" in data: if 'error' in data:
self.encrypted_send_response(request, code, data) self.encrypted_send_response(request, code, data)
else: else:
self.encrypted_send_response(request, code, { self.encrypted_send_response(request, code, {
"api": decrypted["api"], 'api': decrypted['api'],
"response": data}) 'response': data})
if ("api" not in decrypted or "request" not in decrypted if ('api' not in decrypted or 'request' not in decrypted
or type(decrypted["request"]) != dict): or type(decrypted['request']) != dict):
print "Invalid params in API stage" print 'Invalid params in API stage'
encrypted_response_func(400, { "error": "invalid_params" }) encrypted_response_func(400, { 'error': 'invalid_params' })
return True return True
if decrypted["api"] in self.secure_handlers: if decrypted['api'] in self.secure_handlers:
self.secure_handlers[decrypted["api"]](request, self.secure_handlers[decrypted['api']](request,
encrypted_response_func, encrypted_response_func,
decrypted["request"]) decrypted['request'])
else: else:
encrypted_response_func(400, { "error": "unknown_api" }) encrypted_response_func(400, { 'error': 'unknown_api' })
self.post_session_cancel() self.post_session_cancel()
return True return True
...@@ -765,63 +780,63 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -765,63 +780,63 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
return True return True
def do_secure_setup(self, request, response_func, params): def do_secure_setup(self, request, response_func, params):
setup_handlers = { setup_handlers = {
"start": self.do_setup_start, 'start': self.do_setup_start,
"cancel": self.do_setup_cancel } 'cancel': self.do_setup_cancel }
if not "action" in params: if not 'action' in params:
response_func(400, { "error": "invalid_params" }) response_func(400, { 'error': 'invalid_params' })
return return
if params["action"] not in setup: if params['action'] not in setup:
response_func(400, { "error": "invalid_action" }) response_func(400, { 'error': 'invalid_action' })
return return
setup[params["action"]](request, response_func, params) setup[params['action']](request, response_func, params)
def do_secure_status(self, request, response_func, params): def do_secure_status(self, request, response_func, params):
setup = { setup = {
"registration" : { 'registration' : {
"required" : True 'required' : True
}, },
"wifi" : { 'wifi' : {
"required" : True 'required' : True
} }
} }
if self.on_wifi: if self.on_wifi:
setup["wifi"]["status"] = "complete" setup['wifi']['status'] = 'complete'
setup["wifi"]["ssid"] = "" # TODO(noamsml): Add SSID to status setup['wifi']['ssid'] = '' # TODO(noamsml): Add SSID to status
else: else:
setup["wifi"]["status"] = "available" setup['wifi']['status'] = 'available'
if self.cloud_device.get_device_id(): if self.cloud_device.get_device_id():
setup["registration"]["status"] = "complete" setup['registration']['status'] = 'complete'
setup["registration"]["id"] = self.cloud_device.get_device_id() setup['registration']['id'] = self.cloud_device.get_device_id()
else: else:
specific_info["setup"]["registration"] = "available" specific_info['setup']['registration'] = 'available'
def do_setup_start(self, request, response_func, params): def do_setup_start(self, request, response_func, params):
has_wifi = False has_wifi = False
token = None token = None
try: try:
if "wifi" in params: if 'wifi' in params:
has_wifi = True has_wifi = True
ssid = params["wifi"]["ssid"] ssid = params['wifi']['ssid']
passw = params["wifi"]["passphrase"] passw = params['wifi']['passphrase']
if "registration" in params: if 'registration' in params:
token = params["registration"]["ticketID"] token = params['registration']['ticketID']
except KeyError: except KeyError:
print "Invalid params in bootstrap stage" print 'Invalid params in bootstrap stage'
response_func(400, { "error": "invalid_params" }) response_func(400, { 'error': 'invalid_params' })
return return
response_func(200, { "ssid" : ssid }) response_func(200, { 'ssid' : ssid })
if has_wifi: if has_wifi:
self.wifi_handler.switch_to_wifi(ssid, passw, token) self.wifi_handler.switch_to_wifi(ssid, passw, token)
elif token: elif token:
self.cloud_device.register(token) self.cloud_device.register(token)
else: else:
response_func(400, { "error": "invalid_params" }) response_func(400, { 'error': 'invalid_params' })
def do_setup_cancel(self, request, response_func, params): def do_setup_cancel(self, request, response_func, params):
pass pass
def handle_request(self, request): def handle_request(self, request):
...@@ -834,24 +849,24 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -834,24 +849,24 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
if not handled: if not handled:
self.real_send_response(request, 404, self.real_send_response(request, 404,
{ "error": "Not found" }) { 'error': 'Not found' })
def encrypted_send_response(self, request, code, json): def encrypted_send_response(self, request, code, json):
self.real_send_response(request, code, self.real_send_response(request, code,
self.current_session.encrypt(json)) self.current_session.encrypt(json))
def real_send_response(self, request, code, data): def real_send_response(self, request, code, data):
request.write("HTTP/1.1 %d Maybe OK\n" % code) request.write('HTTP/1.1 %d Maybe OK\n' % code)
request.write("Content-Type: application/json\n") request.write('Content-Type: application/json\n')
request.write("Content-Length: %d\n" % len(data)) request.write('Content-Length: %d\n' % len(data))
write_data = "\n%s" % data write_data = '\n%s' % data
request.write(str(write_data)); request.write(str(write_data));
request.finish() request.finish()
def device_state(self): def device_state(self):
return "idle" return 'idle'
def get_common_info(self): def get_common_info(self):
return { "version" : "2.0", return { 'version' : '2.0',
"name" : "Sample Device", 'name' : 'Sample Device',
"device_state" : self.device_state() } 'device_state' : self.device_state() }
def post_session_cancel(self): def post_session_cancel(self):
if self.session_cancel_callback: if self.session_cancel_callback:
self.session_cancel_callback.cancel() self.session_cancel_callback.cancel()
...@@ -876,7 +891,7 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -876,7 +891,7 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
state = State() state = State()
state.load() state.load()
ioloop = tornado.ioloop.IOLoop.instance() ioloop = IOLoop.instance()
handler = WebRequestHandler(ioloop, state) handler = WebRequestHandler(ioloop, state)
...@@ -887,6 +902,6 @@ def logic_stop(): ...@@ -887,6 +902,6 @@ def logic_stop():
atexit.register(logic_stop) atexit.register(logic_stop)
server = tornado.httpserver.HTTPServer(handler.handle_request) server = HTTPServer(handler.handle_request)
server.listen(8080) server.listen(8080)
ioloop.start() ioloop.start()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment