Created
June 27, 2019 19:52
-
-
Save nikhilym/1809ef522c1620cad71af5837fc11335 to your computer and use it in GitHub Desktop.
Geolocation sample skill hosted on HTTPS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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