Skip to content

Instantly share code, notes, and snippets.

@nikhilym
Created June 27, 2019 19:52
Show Gist options
  • Save nikhilym/1809ef522c1620cad71af5837fc11335 to your computer and use it in GitHub Desktop.
Save nikhilym/1809ef522c1620cad71af5837fc11335 to your computer and use it in GitHub Desktop.
Geolocation sample skill hosted on HTTPS
# -*- coding: utf-8 -*-
# This is a skill for getting device location.
import logging
from ask_sdk_core.skill_builder import CustomSkillBuilder
from ask_sdk_core.api_client import DefaultApiClient
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.utils import is_request_type, is_intent_name
from ask_sdk_core.utils import get_supported_interfaces
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response, PermissionStatus
from ask_sdk_model.ui import AskForPermissionsConsentCard
from ask_sdk_model.interfaces.geolocation import (Status, Access)
from ask_sdk_model.ui import SimpleCard
from flask_ask_sdk.skill_adapter import SkillAdapter
from flask import Flask
sb = CustomSkillBuilder(api_client=DefaultApiClient())
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
WELCOME = ("Welcome to the Geolocation sample. To get location information, "
"say whats my location. What do you want to ask?")
WHAT_DO_YOU_WANT = "What do you want to ask?"
NOTIFY_MISSING_PERMISSIONS = ("Skill having trouble accessing your location."
"Please enable Location sharing in "
"the Amazon Alexa app.")
NOTIFY_DEVICE_UNSUPPORTED = "Device doesn't support location based features"
NO_LOCATION_INFO_WITH_PERM = ("There is no location information at the moment. "
"Please try again later")
NOTIFY_MISSING_DEVICE_LOC_SHARING = ("Skill having trouble accessing "
"your location. Please go to your "
"device's settings to turn on location "
"sharing and try again.")
LOCATION_FAILURE = ("Skill having trouble accessing "
"your location at the moment. Please try again later.")
SAMPLE_LOCATION_DATA = ("Skill got your location data. Your coordinates are "
"{} latitudes and {} longitudes. This location "
"accuracy is {} meters")
ERROR = "Uh Oh. Looks like something went wrong."
GOODBYE = "Bye! Thanks for using the Geolocation Sample Skill!"
UNHANDLED = "This skill doesn't support that. Please ask something else"
HELP = ("You can use this skill by asking something like: "
"whats my location?")
permissions = ["alexa::devices:all:geolocation:read"]
class LaunchRequestHandler(AbstractRequestHandler):
# Handler for Skill Launch
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("LaunchRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
handler_input.response_builder.speak(WELCOME).ask(WHAT_DO_YOU_WANT)
return handler_input.response_builder.response
class GetLocationHandler(AbstractRequestHandler):
# Handler for Getting Device Address or asking for location consent
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("LocationIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
req_envelope = handler_input.request_envelope
response_builder = handler_input.response_builder
supported_interfaces = get_supported_interfaces(handler_input)
logger.info("Supported interfaces: {}".format(supported_interfaces))
geolocation_supported = getattr(
supported_interfaces, 'geolocation', None)
logger.info("geolocation supported: {}".format(geolocation_supported))
if geolocation_supported is None:
response_builder.speak(NOTIFY_DEVICE_UNSUPPORTED).set_should_end_session(
True)
return response_builder.response
# Check if permissions set
geolocation_context = req_envelope.context.geolocation
if geolocation_context is None:
perms = req_envelope.context.system.user.permissions.scopes
logger.info("Permissions available: {}".format(perms))
geo_perm = perms.get("alexa::devices:all:geolocation:read", None)
# Check if skill has permissions to use location data
if geo_perm is None or geo_perm.status != PermissionStatus.GRANTED:
response_builder.speak(NOTIFY_MISSING_PERMISSIONS).set_card(
AskForPermissionsConsentCard(permissions=permissions))
return response_builder.response
else:
response_builder.speak(NOTIFY_MISSING_DEVICE_LOC_SHARING).ask(
NO_LOCATION_INFO_WITH_PERM)
return response_builder.response
else:
# Permission available, check if device sharing location
logger.info("Location info: {}".format(geolocation_context))
# location_services = geolocation_context.location_services
# if (location_services is None or
# location_services.status != Status.RUNNING
# or location_services.access != Access.ENABLED):
# response_builder.speak(NOTIFY_MISSING_DEVICE_LOC_SHARING).ask(
# NO_LOCATION_INFO_WITH_PERM)
# return response_builder.response
# Device location sharing on
if geolocation_context.coordinate is None:
# Location retrieval failure, try again message
response_builder.speak(LOCATION_FAILURE).ask(LOCATION_FAILURE)
return response_builder.response
else:
# Got location, do further processing if needed
# Check freshness and accuracy, etc.
accuracy = geolocation_context.coordinate.accuracy_in_meters
latitude = geolocation_context.coordinate.latitude_in_degrees
longitude = geolocation_context.coordinate.longitude_in_degrees
location = SAMPLE_LOCATION_DATA.format(
latitude, longitude, accuracy)
response_builder.speak(location).set_should_end_session(
True).set_card(SimpleCard(
"Your location", location))
return response_builder.response
class SessionEndedRequestHandler(AbstractRequestHandler):
# Handler for Session End
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("SessionEndedRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
return handler_input.response_builder.response
class HelpIntentHandler(AbstractRequestHandler):
# Handler for Help Intent
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("AMAZON.HelpIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
handler_input.response_builder.speak(HELP).ask(HELP)
return handler_input.response_builder.response
class CancelOrStopIntentHandler(AbstractRequestHandler):
# Single handler for Cancel and Stop Intent
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return (is_intent_name("AMAZON.CancelIntent")(handler_input) or
is_intent_name("AMAZON.StopIntent")(handler_input))
def handle(self, handler_input):
# type: (HandlerInput) -> Response
handler_input.response_builder.speak(GOODBYE)
return handler_input.response_builder.response
class CatchAllExceptionHandler(AbstractExceptionHandler):
# Catch all exception handler, log exception and
# respond with custom message
def can_handle(self, handler_input, exception):
# type: (HandlerInput) -> bool
return True
def handle(self, handler_input, exception):
# type: (HandlerInput) -> Response
print("Encountered following exception: {}".format(exception))
speech = "Sorry, there was some problem. Please try again!!"
handler_input.response_builder.speak(speech).ask(speech)
return handler_input.response_builder.response
@sb.global_request_interceptor()
def request_logger(handler_input):
# type: (HandlerInput, Response) -> None
print("Request Envelope: {}".format(handler_input.request_envelope))
@sb.global_response_interceptor()
def response_logger(handler_input, response):
# type: (HandlerInput, Response) -> None
print("Response: {}".format(response))
sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(GetLocationHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_exception_handler(CatchAllExceptionHandler())
# lambda_handler = sb.lambda_handler()
skill_obj = sb.create()
application = Flask(__name__)
# application.config[VERIFY_SIGNATURE_APP_CONFIG] = True
# application.config[VERIFY_TIMESTAMP_APP_CONFIG] = False
skill_response = SkillAdapter(
skill=skill_obj, skill_id=1, verifiers=[], app=application)
skill_response.register(app=application, route="/")
if __name__ == "__main__":
application.run(debug=True, port=8080)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment