Quick Start¶
In here you’ll find a fast introduction to askhome and show you how to get a simple Smart Home Skill up and running.
Installation¶
Install askhome with pip:
$ pip install askhome
If you are deploying to AWS Lambda by uploading zips, install askhome to your directory with:
$ pip install askhome -t /path/to/project-dir
More on deployment later.
Defining Appliances¶
When a Smart Home Skill is installed on Amazon Echo, Alexa first needs to discover all available
appliances with information about what actions they support. With askhome, you can define your
device types by subclassing Appliance
. Methods marked with the
@Appliance.action
decorator will be discoverable and called when
the corresponding request comes in:
from askhome import Appliance
class Light(Appliance):
@Appliance.action
def turn_on(self, request):
pass # Your logic for switching a light on here
@Appliance.action
def turn_off(self, request):
pass # Your logic for switching a light, you guessed it, off here
Now that we’ve defined a light appliance type, lets fill our smart home with some:
from askhome import Smarthome
home = Smarthome()
home.add_appliance('light1', Light, name='Kitchen Light',
description='Turn me on when cutting vegetables.')
home.add_appliance('light2', Light, name='Bedroom Light',
model='Very Bright Light 8000')
We’ve added two lights with some additional info. For all details you can set, check the
Smarthome.add_appliance
method or the official
DiscoverAppliancesResponse
documentation.
All that’s left to do is expose a handler for our AWS Lambda instance (more on that in deployment):
lambda_handler = home.lambda_handler
And that’s it! We’ve got a fully functioning Smart Home Skill that controls our lights. It can be initialized with:
“Alexa, discover my devices.”
And then to control the lights:
“Alexa, turn on the kitchen light.”
Handling Requests¶
When the method wrapped with @Appliance.action
gets called, it
receives a Request
object as argument. It has some basic
useful attributes such as payload
or
name
, but what’s special about it is that for every
action type a specific Request
subclass is passed. These
subclasses have additional helpful attributes and a
response
method which simplifies the response creation.
For instance a set_target_temperature
action receives a request that can do this:
class Heater(Appliance):
@Appliance.action
def set_target_temperature(self, request):
print request.temperature
return request.response(request.temperature,
mode='HEAT',
previous_temperature=21.3,
previous_mode='AUTO')
If the action method doesn’t return anything (returns None
), success is implied.
Actions Overview¶
- Possible action methods and their corresponding
Request
types passed are: - turn_on(
Request
) - turn_off(
Request
) - set_percentage(
PercentageRequest
) - increment_percentage(
PercentageRequest
) - decrement_percentage(
PercentageRequest
) - set_target_temperature(
ChangeTemperatureRequest
) - increment_target_temperature(
ChangeTemperatureRequest
) - decrement_target_temperature(
ChangeTemperatureRequest
) - get_target_temperature(
GetTargetTemperatureRequest
) - get_temperature_reading(
TemperatureReadingRequest
) - set_lock_state(
LockStateRequest
) - get_lock_state(
LockStateRequest
)
- turn_on(
Here is a sample usage of all possible actions:
from askhome.requests import *
class UltimateAppliance(Appliance):
# The action_for decorator can mark a method for multiple actions
@Appliance.action_for('turn_on', 'turn_off')
def turn_on_off(self, request):
# type: (Request) -> Optional[dict]
pass # nothing special here
@Appliance.action_for('set_percentage', 'increment_percentage',
'decrement_percentage')
def control_percentage(self, request):
# type: (PercentageRequest) -> Optional[dict]
print request.percentage
print request.delta_percentage
@Appliance.action_for('set_target_temperature',
'increment_target_temperature',
'decrement_target_temperature')
def control_temperature(self, request):
# type: (ChangeTemperatureRequest) -> Optional[dict]
print request.temperature
print request.delta_temperature
return request.response(22.8,
mode='HEAT',
previous_temperature=21.3,
previous_mode='AUTO')
@Appliance.action
def get_target_temperature(self, request):
# type: (GetTargetTemperatureRequest) -> Optional[dict]
return request.response(21.8,
cooling_temperature=20
heating_temperature=23,
mode='CUSTOM',
mode_name='mode name')
@Appliance.action
def get_temperature_reading(self, request):
# type: (TemperatureReadingRequest) -> Optional[dict]
return request.response(21.8, timestamp=datetime.now())
@Appliance.action_for('set_lock_state', 'get_lock_state')
def lock_state(self, request):
# type: (LockStateRequest) -> Optional[dict]
return request.response('LOCKED')
For further information about these actions see the official documentation.
Error Responses¶
If the user asked an invalid request or something goes wrong during the action execution, the Smart Home API offers plenty of possible error responses. To respond with an error, simply raise one of askhome’s exceptions, like this:
from askhome.exceptions import ValueOutOfRangeError
class Heater(Appliance):
@Appliance.action
def set_target_temperature(self, request):
if request.temperature not in range(15, 25):
raise ValueOutOfRangeError(15, 25)
All possible exceptions can be found here
or at the official
error messages documentation.
Deployment¶
Unlike the Custom Skills, Smart Home Skills have to be hosted on AWS Lambda instances. To create a skill and deploy it to Lambda, follow the official tutorial. When it comes to uploading your code, you have to package your libraries with it. You can do that with a local pip installation and then uploading a zip of your project with all its dependencies included.
Deploying with Zappa¶
Zappa is an awesome tool to deploy WSGI apps to Lambda. Smart Home Skills are not using the WSGI interface, but we can still use Zappa to automate our deployments. It also comes with advantages like precompiled python packages (such as pyOpenSSL) which would otherwise have to be compiled on AWS machines.
To use it, first create a virtualenv for your project:
$ virtualenv .venv
$ source .venv/Scripts/activate
Then install the required packages:
$ pip install Zappa askhome
Create a zappa_settings.yml
configuration file for Zappa:
dev:
s3_bucket: smart-home-skill-dev-deploy
lambda_handler: main.lambda_handler # name of your file and exposed handler
aws_region: us-east-1 # region has to match your Echo version
timeout_seconds: 10
memory_size: 128
keep_warm: false
touch: false # keep Zappa from sending WSGI requests to your skill
Finally, let Zappa do its work:
$ zappa deploy
That should create a Lambda function, but you still need to manually add the trigger and link the function to your skill as described in the official tutorial. After that your Echo should respond to your commands!
Next, you can go to the official Smart Home Skill API documentation for detailed request information or continue to Advanced Usage.