import boto3 from urllib.request import Request 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, get_account_linking_access_token, get_request_type, get_intent_name, get_slot_value_v2, get_simple_slot_values from ask_sdk_core.handler_input import HandlerInput from ask_sdk_model.ui import SimpleCard, output_speech from ask_sdk_model import Response from ask_sdk_core.skill_builder import SkillBuilder import ask_sdk_core.utils as ask_utils import logging import json import time import requests logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) sb = SkillBuilder() client = boto3.client('dynamodb') class CheckAccountLinkedHandler(AbstractRequestHandler): def can_handle(self, handler_input): print("check account is done") return not get_account_linking_access_token(handler_input) def handle(self, handler_input): print("Can CheckAccountLinkedHandler-------------------------------------------------------") return handler_input.response_builder.speak("Need to link account in Alexa App").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): print("Can CancelOrStopIntentHandler-------------------------------------------------------") # type: (HandlerInput) -> Response speech_text = "Goodbye!" handler_input.response_builder.speak(speech_text).set_card( SimpleCard("My Car", speech_text)) return handler_input.response_builder.response class FallbackIntentHandler(AbstractRequestHandler): """ This handler will not be triggered except in supported locales, so it is safe to deploy on any locale. """ def can_handle(self, handler_input): # type: (HandlerInput) -> bool return is_intent_name("AMAZON.FallbackIntent")(handler_input) def handle(self, handler_input): print("Can FallbackIntentHandler-------------------------------------------------------") # type: (HandlerInput) -> Response speech_text = ( "The my car skill can't help you with that. " "You can say hello!!") reprompt = "You can say hello!!" handler_input.response_builder.speak(speech_text).ask(reprompt) return handler_input.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): print("Can SessionEndedRequestHandler-------------------------------------------------------") # type: (HandlerInput) -> Response 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, Exception) -> bool return True def handle(self, handler_input, exception): print("Can CatchAllExceptionHandler-------------------------------------------------------") # type: (HandlerInput, Exception) -> Response logger.error(exception, exc_info=True) speech = "Sorry, there was some problem. Please try again!!" handler_input.response_builder.speak(speech).ask(speech) return handler_input.response_builder.response class RequestInfoHandler(AbstractRequestHandler): def can_handle(self, handler_input): logger.info("handler input request_envelope and context is: ") logger.info(handler_input.request_envelope) logger.info(handler_input.context) return is_request_type("IntentRequest")(handler_input) and is_intent_name("RequestInfoIntent")(handler_input) def handle(self, handler_input): print( "Can RequestInfoHandler-------------------------------------------------------") output_string = "You current vehicle status: " + \ get_status(handler_input) return handler_input.response_builder.speak("Here is what you are looking for, " + output_string).set_card( SimpleCard("Car Status Check", output_string) ).response class CarCtrlAirCondPwrHandler(AbstractRequestHandler): def can_handle(self, handler_input): logger.info("handler input request_envelope and context is: ") logger.info(handler_input.request_envelope) logger.info(handler_input.context) return is_request_type("IntentRequest")(handler_input) and is_intent_name("CarCtrlAirCondPwrIntent")(handler_input) def handle(self, handler_input): print("Can CarCtrlAirCondPwrHandler-------------------------------------------------------") output_string = "Sending remote vehicle control commands: " + \ set_status(handler_input) return handler_input.response_builder.speak("Here is what you are looking for, " + output_string).set_card( SimpleCard("Remote vehicle Control", output_string) ).response class CarCtrlAirCondTempHandler(AbstractRequestHandler): def can_handle(self, handler_input): logger.info("handler input request_envelope and context is: ") logger.info(handler_input.request_envelope) logger.info(handler_input.context) return is_request_type("IntentRequest")(handler_input) and is_intent_name("CarCtrlAirCondTempIntent")(handler_input) def handle(self, handler_input): print("Can CarCtrlAirCondTempHandler-------------------------------------------------------") output_string = "Sending remote vehicle control commands: " + \ set_status(handler_input) return handler_input.response_builder.speak("Here is what you are looking for, " + output_string).set_card( SimpleCard("Remote vehicle Control", output_string) ).response class CarCtrlAirCondFanHandler(AbstractRequestHandler): def can_handle(self, handler_input): print("handler input request_envelope and context is: ") return is_request_type("IntentRequest")(handler_input) and is_intent_name("CarCtrlAirCondFanIntent")(handler_input) def handle(self, handler_input): print("Can CarCtrlAirCondTempHandler-------------------------------------------------------") output_string = "Sending remote vehicle control commands: " + \ set_status(handler_input) return handler_input.response_builder.speak("Here is what you are looking for, " + output_string).set_card( SimpleCard("Remote vehicle Control", output_string) ).response # Util functions def get_vin_key(handler_input): access_token = get_account_linking_access_token(handler_input) content = requests.get('https://api.amazon.com/user/profile?access_token='+access_token).content user_email_address = json.loads(content)['email'] data = client.get_item( TableName='user_table', Key={ 'email_address': { 'S': user_email_address } }) return data["Item"]["vin"]["S"] def get_status(handler_input): intent = ask_utils.get_intent_name(handler_input) key = get_vin_key(handler_input) resolved_id = get_resolved_id( handler_input.request_envelope.request, "infoTypeRequested") data = read_dynamodb(key) output_string = "with " if resolved_id == "MLG": output_string = "with " + data["Item"]["MLG"]["S"] + \ " " + data["Item"]["MLG_unit"]["S"] + " mileage left" if resolved_id == "BAT": output_string = "battery with " + \ data["Item"]["BAT"]["S"] + " " + \ data["Item"]["BAT_unit"]["S"] + " left" return output_string def set_status(handler_input): intent = ask_utils.get_intent_name(handler_input) output_string = " Set status: " vin_key = get_vin_key(handler_input) if intent == "CarCtrlAirCondPwrIntent": resolved_id = get_resolved_id( handler_input.request_envelope.request, "SetConditionRequested") print("------Set Status------ with INTENT = " + intent + "------ with Resolve ID = " + resolved_id) output_string = set_ac_pwr(resolved_id, vin_key) if intent == "CarCtrlAirCondTempIntent": slot_values = ask_utils.get_slot_value_v2(handler_input, "AC_TEMP_SET") print(format(slot_values)) print("------Set Status------ with INTENT = " + intent + "------ with Slots AC_TEMP_SET = " + slot_values.value) output_string = set_ac_status("AC_TEMP_SET", slot_values.value, vin_key) if intent == "CarCtrlAirCondFanIntent": slot_values = ask_utils.get_slot_value_v2(handler_input, "AC_FAN_SET") print(format(slot_values)) print("------Set Status------ with INTENT = " + intent + "------ with Slots AC_FAN_SET = " + slot_values.value) output_string = set_ac_status("AC_FAN_SET", slot_values.value, vin_key) return output_string def get_ac_status(key): data = read_dynamodb(key) ac_status = "OFF" if data["Item"]["AC_PWR_SET"]["S"] == "1": ac_status = "ON" output_string = "air condition is " + data["Item"]["AC_PWR_SET"]["S"] + " with temperature of" + \ data["Item"]["AC_TEMP_SET"]["S"] + \ " and FAN speed level of " + data["Item"]["AC_FAN_SET"]["S"] return output_string def set_ac_pwr(key, vin_key): output_string = "Air conditioner ERROR" if (key == "AC_PWR_ON"): set_dynamodb("AC_PWR_SET", "ON", vin_key) output_string = "Air conditioner ON" if (key == "AC_PWR_OFF"): set_dynamodb("AC_PWR_SET", "OFF", vin_key) output_string = "Air conditioner OFF" return output_string def set_ac_status(key, value, set_ac_status, vin_key): output_string = "Air conditioner ERROR" if (key == "AC_TEMP_SET"): set_dynamodb(key, value, vin_key) output_string = "Set Air conditioner Temperature to " + value + " degrees" if (key == "AC_FAN_SET"): set_dynamodb(key, value, vin_key) output_string = "Set Air conditioner Fan Speed to Level " + value return output_string sb.add_request_handler(CheckAccountLinkedHandler()) sb.add_request_handler(RequestInfoHandler()) sb.add_request_handler(CarCtrlAirCondPwrHandler()) sb.add_request_handler(CarCtrlAirCondTempHandler()) sb.add_request_handler(CarCtrlAirCondFanHandler()) # default_request_handler sb.add_request_handler(CancelOrStopIntentHandler()) sb.add_request_handler(FallbackIntentHandler()) sb.add_request_handler(SessionEndedRequestHandler()) sb.add_exception_handler(CatchAllExceptionHandler()) lambda_handler = sb.lambda_handler() # Utility functions def get_resolved_id(request, slot_name): """Resolve the slot name from the request using resolutions.""" # type: (IntentRequest, str) -> Union[str, None] # slots_res_id = handler_input.request_envelope.request.intent.slots.infoTypeRequested.resolutions.resolutions_per_authority[0].values[0].value.id try: return (request.intent.slots[slot_name].resolutions. resolutions_per_authority[0].values[0].value.id) except (AttributeError, ValueError, KeyError, IndexError, TypeError) as e: logger.info("Couldn't resolve {} for request: {}".format( slot_name, request)) logger.info(str(e)) return None TABLE_NAME = '' def read_dynamodb(key): try: data = client.get_item( TableName='car_status_table', Key={ 'vin': { 'S': key } }) except: logger.error("Can not read dynamo table") raise else: return data def set_dynamodb(key, value, vin_key): try: client.update_item( TableName='car_status_table', Key={ 'vin': { 'S': vin_key } }, AttributeUpdates={ key: { 'Value': { 'S': value } }, 'TS':{ 'Value': { 'S': str(int(round(time.time() * 1000))) } } } ) except: logger.error("Can not set dynamodb table") raise