Commit 16ee2632 authored by noamsml@chromium.org's avatar noamsml@chromium.org

Fixes for wifi side of GCD prototype

1.  Moved actual device indicator to config.json
2.  Wireless interface now part of config.json
3.  LED path now part of config.json
4.  udhcpd config now generated by script

This should make the script a fair bit more robust and allow it to work on any
machine.

In addition, updated the SSID to the new format.

BUG=
NOTRY=true

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284171 0039d316-1c4b-4281-b951-d872f2087c98
parent acc18a83
...@@ -20,6 +20,7 @@ import base64 ...@@ -20,6 +20,7 @@ import base64
import datetime import datetime
import json import json
import os import os
import random
import subprocess import subprocess
import time import time
import traceback import traceback
...@@ -35,13 +36,13 @@ from tornado.ioloop import IOLoop ...@@ -35,13 +36,13 @@ 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' _CONFIG_FILE = 'config.json'
_API_DISCOVERY_FILE = 'discovery.json' _API_DISCOVERY_FILE = 'discovery.json'
_DEVICE_STATE_FILE = 'device_state.json' _DEVICE_STATE_FILE = 'device_state.json'
_DEVICE_SETUP_SSID = 'GCDPrototype.camera.privet' _DEVICE_SETUP_SSID = 'GCD Prototype %02d..Bcamprv'
_DEVICE_NAME = 'GCD Prototype' _DEVICE_NAME = 'GCD Prototype'
_DEVICE_TYPE = 'camera' _DEVICE_TYPE = 'vendor'
_DEVICE_PORT = 8080 _DEVICE_PORT = 8080
DEVICE_DRAFT = { DEVICE_DRAFT = {
...@@ -64,12 +65,12 @@ DEVICE_DRAFT = { ...@@ -64,12 +65,12 @@ DEVICE_DRAFT = {
} }
} }
wpa_supplicant_cmd = 'wpa_supplicant -Dwext -iwlan0 -cwpa_supplicant.conf' wpa_supplicant_cmd = 'wpa_supplicant -Dwext -i%s -cwpa_supplicant.conf'
ifconfig_cmd = 'ifconfig wlan0 192.168.0.3' ifconfig_cmd = 'ifconfig %s 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 %s'
dhclient_renew = 'dhclient wlan0' dhclient_renew = 'dhclient %s'
dhcpd_cmd = 'udhcpd -f /etc/udhcpd.conf' dhcpd_cmd = 'udhcpd -f udhcpd.conf'
wpa_supplicant_conf = 'wpa_supplicant.conf' wpa_supplicant_conf = 'wpa_supplicant.conf'
...@@ -84,8 +85,22 @@ network={ ...@@ -84,8 +85,22 @@ network={
psk="%s" psk="%s"
}""" }"""
led_path = '/sys/class/leds/ath9k_htc-phy0/' hostapd_conf = 'hostapd-min.conf'
hostapd_template = """
interface=%s
driver=nl80211
ssid=%s
channel=1
"""
udhcpd_conf = 'udhcpd.conf'
udhcpd_template = """
start 192.168.0.20
end 192.168.0.254
interface %s
"""
class DeviceUnregisteredError(Exception): class DeviceUnregisteredError(Exception):
pass pass
...@@ -105,7 +120,7 @@ class CommandWrapperReal(object): ...@@ -105,7 +120,7 @@ class CommandWrapperReal(object):
"""Command wrapper that executs shell commands.""" """Command wrapper that executs shell commands."""
def __init__(self, cmd): def __init__(self, cmd):
if type(cmd) == str: if type(cmd) in [str, unicode]:
cmd = cmd.split() cmd = cmd.split()
self.cmd = cmd self.cmd = cmd
self.cmd_str = ' '.join(cmd) self.cmd_str = ' '.join(cmd)
...@@ -160,8 +175,9 @@ class CloudCommandHandlerFake(object): ...@@ -160,8 +175,9 @@ class CloudCommandHandlerFake(object):
class CloudCommandHandlerReal(object): class CloudCommandHandlerReal(object):
"""Executes device commands.""" """Executes device commands."""
def __init__(self, ioloop): def __init__(self, ioloop, led_path):
self.ioloop = ioloop self.ioloop = ioloop
self.led_path = led_path
def handle_command(self, command_name, args): def handle_command(self, command_name, args):
if command_name == 'flashLED': if command_name == 'flashLED':
...@@ -180,7 +196,7 @@ class CloudCommandHandlerReal(object): ...@@ -180,7 +196,7 @@ 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(self.led_path, 'brightness'), 'w')
if value: if value:
file_trigger.write('1') file_trigger.write('1')
...@@ -202,10 +218,12 @@ class WifiHandler(object): ...@@ -202,10 +218,12 @@ class WifiHandler(object):
"""Token is optional, and all delegates should support it being None.""" """Token is optional, and all delegates should support it being None."""
raise Exception('Unhandled condition: WiFi connected') raise Exception('Unhandled condition: WiFi connected')
def __init__(self, ioloop, state, delegate): def __init__(self, ioloop, state, config, setup_ssid, delegate):
self.ioloop = ioloop self.ioloop = ioloop
self.state = state self.state = state
self.delegate = delegate self.delegate = delegate
self.setup_ssid = setup_ssid
self.interface = config['wireless_interface']
def start(self): def start(self):
raise Exception('Start not implemented!') raise Exception('Start not implemented!')
...@@ -221,13 +239,18 @@ class WifiHandlerReal(WifiHandler): ...@@ -221,13 +239,18 @@ class WifiHandlerReal(WifiHandler):
devices for testing the wifi-specific logic. devices for testing the wifi-specific logic.
""" """
def __init__(self, ioloop, state, delegate): def __init__(self, ioloop, state, config, setup_ssid, delegate):
super(WifiHandlerReal, self).__init__(ioloop, state, delegate) super(WifiHandlerReal, self).__init__(ioloop, state, config,
setup_ssid, delegate)
self.command_wrapper = CommandWrapperReal if config['simulate_commands']:
self.hostapd = self.CommandWrapper(hostapd_cmd) self.command_wrapper = CommandWrapperFake
self.wpa_supplicant = self.CommandWrapper(wpa_supplicant_cmd) else:
self.dhcpd = self.CommandWrapper(dhcpd_cmd) self.command_wrapper = CommandWrapperReal
self.hostapd = self.command_wrapper(hostapd_cmd)
self.wpa_supplicant = self.command_wrapper(
wpa_supplicant_cmd % self.interface)
self.dhcpd = self.command_wrapper(dhcpd_cmd)
def start(self): def start(self):
if self.state.has_wifi(): if self.state.has_wifi():
...@@ -236,21 +259,30 @@ class WifiHandlerReal(WifiHandler): ...@@ -236,21 +259,30 @@ class WifiHandlerReal(WifiHandler):
self.start_hostapd() self.start_hostapd()
def start_hostapd(self): def start_hostapd(self):
hostapd_config = open(hostapd_conf, 'w')
hostapd_config.write(hostapd_template % (self.interface, self.setup_ssid))
hostapd_config.close()
self.hostapd.start() self.hostapd.start()
time.sleep(3) time.sleep(3)
self.run_command(ifconfig_cmd) self.run_command(ifconfig_cmd % self.interface)
self.dhcpd.start() self.dhcpd.start()
def switch_to_wifi(self, ssid, passwd, token): def switch_to_wifi(self, ssid, passwd, token):
try: try:
udhcpd_config = open(udhcpd_conf, 'w')
udhcpd_config.write(udhcpd_template % self.interface)
udhcpd_config.close()
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()
self.dhcpd.end() self.dhcpd.end()
self.wpa_supplicant.start() self.wpa_supplicant.start()
self.run_command(dhclient_release) self.run_command(dhclient_release % self.interface)
self.run_command(dhclient_renew) self.run_command(dhclient_renew % self.interface)
self.state.set_wifi(ssid, passwd) self.state.set_wifi(ssid, passwd)
self.delegate.on_wifi_connected(token) self.delegate.on_wifi_connected(token)
...@@ -276,8 +308,9 @@ class WifiHandlerReal(WifiHandler): ...@@ -276,8 +308,9 @@ class WifiHandlerReal(WifiHandler):
class WifiHandlerPassthrough(WifiHandler): class WifiHandlerPassthrough(WifiHandler):
"""Passthrough wifi handler.""" """Passthrough wifi handler."""
def __init__(self, ioloop, state, delegate): def __init__(self, ioloop, state, config, setup_ssid, delegate):
super(WifiHandlerPassthrough, self).__init__(ioloop, state, delegate) super(WifiHandlerPassthrough, self).__init__(ioloop, state, config,
setup_ssid, delegate)
def start(self): def start(self):
self.delegate.on_wifi_connected(None) self.delegate.on_wifi_connected(None)
...@@ -373,6 +406,33 @@ class State(object): ...@@ -373,6 +406,33 @@ class State(object):
return self.device_id_ return self.device_id_
class Config(object):
"""Configuration parameters (should not change)"""
def __init__(self):
if not os.path.isfile(_CONFIG_FILE):
config = {
'oauth_client_id': '',
'oauth_secret': '',
'api_key': '',
'wireless_interface': ''
}
config_f = open(_CONFIG_FILE + '.sample', 'w')
config_f.write(json.dumps(credentials, sort_keys=True,
indent=2, separators=(',', ': ')))
config_f.close()
raise Exception('Missing ' + _CONFIG_FILE)
config_f = open(_CONFIG_FILE)
config = json.load(config_f)
config_f.close()
self.config = config
def __getitem__(self, item):
if item in self.config:
return self.config[item]
return None
class MDnsWrapper(object): class MDnsWrapper(object):
"""Handles mDNS requests to device.""" """Handles mDNS requests to device."""
...@@ -432,28 +492,13 @@ class CloudDevice(object): ...@@ -432,28 +492,13 @@ class CloudDevice(object):
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, command_wrapper, delegate): def __init__(self, ioloop, state, config, command_wrapper, 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, sort_keys=True,
indent=2, separators=(',', ': ')))
credentials_f.close()
raise Exception('Missing ' + _API_CLIENT_FILE)
credentials_f = open(_API_CLIENT_FILE)
credentials = json.load(credentials_f)
credentials_f.close()
self.oauth_client_id = credentials['oauth_client_id'] self.oauth_client_id = config['oauth_client_id']
self.oauth_secret = credentials['oauth_secret'] self.oauth_secret = config['oauth_secret']
self.api_key = credentials['api_key'] self.api_key = config['api_key']
if not os.path.isfile(_API_DISCOVERY_FILE): if not os.path.isfile(_API_DISCOVERY_FILE):
raise Exception('Download https://developers.google.com/' raise Exception('Download https://developers.google.com/'
...@@ -470,7 +515,7 @@ class CloudDevice(object): ...@@ -470,7 +515,7 @@ class CloudDevice(object):
self.device_id = None self.device_id = None
self.credentials = None self.credentials = None
self.delegate = delegate self.delegate = delegate
self.command_handler = command_wrapper(ioloop) self.command_handler = command_wrapper
def try_start(self, token): def try_start(self, token):
"""Tries start or register device.""" """Tries start or register device."""
...@@ -682,24 +727,35 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -682,24 +727,35 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
return 'complete' return 'complete'
def __init__(self, ioloop, state): def __init__(self, ioloop, state):
if os.path.exists('on_real_device'): self.config = Config()
if self.config['on_real_device']:
mdns_wrappers = CommandWrapperReal mdns_wrappers = CommandWrapperReal
cloud_wrapper = CloudCommandHandlerReal
wifi_handler = WifiHandlerReal wifi_handler = WifiHandlerReal
self.setup_real()
else: else:
mdns_wrappers = CommandWrapperReal mdns_wrappers = CommandWrapperReal
cloud_wrapper = CloudCommandHandlerFake
wifi_handler = WifiHandlerPassthrough wifi_handler = WifiHandlerPassthrough
if self.config['led_path']:
cloud_wrapper = CloudCommandHandlerReal(ioloop,
self.config['led_path'])
self.setup_real(self.config['led_path'])
else:
cloud_wrapper = CloudCommandHandlerFake(ioloop)
self.setup_fake() self.setup_fake()
self.cloud_device = CloudDevice(ioloop, state, cloud_wrapper, self) self.setup_ssid = _DEVICE_SETUP_SSID % random.randint(0,99)
self.wifi_handler = wifi_handler(ioloop, state, self) self.cloud_device = CloudDevice(ioloop, state, self.config,
cloud_wrapper, self)
self.wifi_handler = wifi_handler(ioloop, state, self.config,
self.setup_ssid, self)
self.mdns_wrapper = MDnsWrapper(mdns_wrappers) self.mdns_wrapper = MDnsWrapper(mdns_wrappers)
self.on_wifi = False self.on_wifi = False
self.registered = False self.registered = False
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,
...@@ -733,14 +789,14 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate): ...@@ -733,14 +789,14 @@ class WebRequestHandler(WifiHandler.Delegate, CloudDevice.Delegate):
print 'Skipping device setup' print 'Skipping device setup'
@staticmethod @staticmethod
def setup_real(): def setup_real(led_path):
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()
def start(self): def start(self):
self.wifi_handler.start() self.wifi_handler.start()
self.mdns_wrapper.set_setup_name(_DEVICE_SETUP_SSID) self.mdns_wrapper.set_setup_name(self.setup_ssid)
self.mdns_wrapper.start() self.mdns_wrapper.start()
@get_only @get_only
......
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