Example #1
0
def handle_power_state(request):
    # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
    # TODO: handle other scenarios, other than on/off?
    endpoint_id = request['directive']['endpoint']['endpointId']
    name = name = request['directive']['header']['name']
    power_state_value = 'ON' if name == 'TurnOn' else 'OFF'
    correlation_token = request['directive']['header'][
        'correlationToken']  # required in the response
    bearer_token = request['directive']['endpoint']['scope'][
        'token']  # identifies the user

    intof_id = umap.token_intof_map(bearer_token)
    if (intof_id == None):
        response = get_error_response('INTERNAL_ERROR',
                                      'Unable to get the Intof user id.')
        return send_response(response.get())

    # TODO: Check for device error in setting the state
    state_set = set_device_state(intof_id, endpoint_id, power_state_value)
    if (state_set == False):
        print('-   Error setting the device state!')
        response = get_error_response(
            'ENDPOINT_UNREACHABLE', 'The device is not responding.'
        )  # TODO: use friendly name in the response
        return send_response(response.get())
    response = AlexaResponse(correlation_token=correlation_token)
    response.add_context_property(namespace='Alexa.PowerController',
                                  name='powerState',
                                  value=power_state_value)
    return response
def control_device(request):
    """
    Control a specific device
    """
    power_state_value = 'OFF' if request['directive']['header'][
        'name'] == 'TurnOff' else 'ON'
    endpoint_id = request['directive']['endpoint']['endpointId']
    correlation_token = request['directive']['header']['correlationToken']

    # Check for an error when setting the state
    state_set = set_device_state(endpoint_id=endpoint_id,
                                 value=power_state_value)
    if state_set is None:
        return error(type='ENDPOINT_UNREACHABLE',
                     message='Unable to reach endpoint database.')
    elif not state_set:
        return error(
            type='ENDPOINT_UNREACHABLE',
            message='I did not get a response from the device controller.')

    apcr = AlexaResponse(correlation_token=correlation_token)
    apcr.add_context_property(namespace='Alexa.PowerController',
                              name='powerState',
                              value=power_state_value)
    return success(apcr.get())
    def send_event(alexa_namespace, alexa_name, endpoint_id, token, payload):

        remove_endpoint = alexa_name is not "ChangeReport"
        alexa_response = AlexaResponse(namespace=alexa_namespace,
                                       name=alexa_name,
                                       endpoint_id=endpoint_id,
                                       token=token,
                                       remove_endpoint=remove_endpoint)
        alexa_response.set_payload(payload)
        payload = json.dumps(alexa_response.get())
        print('LOG api_handler_event.send_event.payload:')
        print(payload)

        # TODO Map to correct endpoint for Europe: https://api.eu.amazonalexa.com/v3/events
        # TODO Map to correct endpoint for Far East: https://api.fe.amazonalexa.com/v3/events
        alexa_event_gateway_uri = 'api.amazonalexa.com'
        connection = http.client.HTTPSConnection(alexa_event_gateway_uri)
        headers = {
            'Authorization': "Bearer " + token,
            'Content-Type': "application/json;charset=UTF-8",
            'Cache-Control': "no-cache"
        }
        connection.request('POST', '/v3/events', payload, headers)
        response = connection.getresponse()
        print('LOG api_handler_event.send_event HTTP Status code: ' +
              str(response.getcode()))
        return response
Example #4
0
def get_error_response(error_type, error_msg):
    response = AlexaResponse(name='ErrorResponse',
                             payload={
                                 'type': error_type,
                                 'message': error_msg
                             })
    return response
def error(**kwargs):
    """
    Build an error response
    """
    rsp = AlexaResponse(name='ErrorResponse', payload=kwargs).get()
    logger.debug(f'lambda handler failed; response: {json.dumps(rsp)}')
    return rsp
def handle_control(name, event):
    endpoint_id = event['directive']['endpoint']['endpointId']
    power_state_value = 'OFF' if name == 'TurnOff' else 'ON'
    correlation_token = event['directive']['header']['correlationToken']

    state_sent = send_device_state(endpoint_id=endpoint_id,
                                   state='powerState',
                                   value=power_state_value)
    if not state_sent:
        return AlexaResponse(name='ErrorResponse',
                             payload={
                                 'type': 'ENDPOINT_UNREACHABLE',
                                 'message': 'Unable to reach endpoint.'
                             }).get()

    state_save = save_device_state(endpoint_id=endpoint_id,
                                   state='powerState',
                                   value=power_state_value)
    if not state_save:
        return AlexaResponse(name='ErrorResponse',
                             payload={
                                 'type': 'ENDPOINT_UNREACHABLE',
                                 'message': 'Unable to reach dynamo.'
                             }).get()

    apcr = AlexaResponse(correlation_token=correlation_token)
    apcr.add_context_property(namespace=NAMESPACE_CONTROL,
                              name='powerState',
                              value=power_state_value,
                              endpoint_id=endpoint_id)
    return apcr.get()
Example #7
0
    def create(self, request):
        print("LOG event.create.request:", request)

        try:
            json_object = json.loads(request['body'])
            endpoint_user_id = json_object['event']['endpoint']['userId']  # Expect a Profile
            endpoint_name = json_object['event']['endpoint']['id']  # Expect a valid AWS IoT Thing Name
            endpoint_state = json_object['event']['endpoint']['state']  # Expect a state value, ex: ON or OFF
            sku = json_object['event']['endpoint']['sku']  # Expect a meaningful type, ex: SW00

            try:
                # Update the IoT Thing
                response = iot_aws.update_thing(
                    thingName=endpoint_name,
                    attributePayload={
                        'attributes': {
                            'state': endpoint_state,
                            'proactively_reported': 'True',
                            'user_id': endpoint_user_id
                        }
                    }
                )
                print('LOG event.create.iot_aws.update_thing.response:', str(response))

                # Update Alexa with a Proactive State Update
                if endpoint_user_id == 0:
                    print('LOG PSU: Not sent for user_id of 0')
                else:
                    response_psu = self.send_psu(endpoint_user_id, endpoint_name, endpoint_state)
                    print('LOG PSU response:', response_psu)

            except ClientError as e:
                alexa_response = AlexaResponse(name='ErrorResponse', message=e)
                alexa_response.set_payload(
                    {
                        'type': 'INTERNAL_ERROR',
                        'message': e
                    }
                )
                response = alexa_response.get()

            return response

        except KeyError as key_error:
            return "KeyError: " + str(key_error)
Example #8
0
def handle_grant (request):
    print ('-  Code grant triggered!')
    # Note: This sample accepts any grant request
    # Use the Grant-Code and Grantee-Token to get Access-Token and Refresh-Token and save them in a DB
    grant_code = request['directive']['payload']['grant']['code']
    grantee_token = request['directive']['payload']['grantee']['token']
    print ('-  Grant code: ', grant_code)
    print ('-  Grantee token: ', grantee_token)
    result = save_grant (grant_code, grantee_token)
    if (result == False):
        response = AlexaResponse (
                        name = 'ErrorResponse',
                        payload = {
                            'type': 'INTERNAL_ERROR', 
                            'message': 'Failed to save grant code & token in DB.'
                        })
        return response 
    response = AlexaResponse (namespace='Alexa.Authorization', name='AcceptGrant.Response')
    return response
Example #9
0
def validate_request(request):
    if 'directive' not in request:
        response = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INVALID_DIRECTIVE',
                'message': 'Invalid Alexa request; Missing key: directive'
            })
        return response
    # payload version must be 3
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        response = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'Only Smart Home API version 3 is supported.'
            })
        return response
    print('-  Request validated.')
    return (None)  # None = no error response; successfully validated
Example #10
0
def handle_discovery(request):
    print('-  Discovery initiated!')
    token = request['directive']['payload']['scope']['token']
    intof_id = umap.token_intof_map(token)
    if (intof_id == None):
        response = get_error_response(
            'REGISTRATION_ERROR', 'Unable to get the Intof user id.'
        )  # INVALID_AUTHORIZATION_CREDENTIAL / EXPIRD
        #return send_response (response.get())
        return response
    devices = device.get_devices(intof_id)
    if (devices == None):
        response = get_error_response(
            'DISCOVERY_ERROR', 'Unable to get your registered devices.')
    if len(devices) == 0:
        response = get_error_response(
            'DISCOVERY_ERROR', 'You do not have any registered devices.')
        return send_response(response.get())
    response = AlexaResponse(namespace='Alexa.Discovery',
                             name='Discover.Response')
    # create a basic alexa capability...
    capability_alexa = response.create_payload_endpoint_capability()
    # .. and a more specific capability
    capability_powercontroller = response.create_payload_endpoint_capability(
        interface='Alexa.PowerController', supported=[{
            'name': 'powerState'
        }])
    for i in range(len(devices)):
        response.add_payload_endpoint(
            friendly_name=devices[i][1],
            endpoint_id=devices[i][0],
            capabilities=[capability_alexa, capability_powercontroller])
    return response
    def test_discovery(self):
        adr = AlexaResponse(namespace="Alexa.Discovery", name="Discover.Response")
        capability_alexa = adr.create_payload_endpoint_capability()
        capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
            interface="Alexa.PowerController",
            supported=[{"name": "powerState"}])
        adr.add_payload_endpoint(capabilities=[capability_alexa, capability_alexa_powercontroller])
        response = adr.get()

        self.assertEqual(response['event']['header']['namespace'], 'Alexa.Discovery')
        self.assertEqual(response['event']['header']['name'], 'Discover.Response')
        self.assertEqual(response['event']['payload']['endpoints'][0]['friendlyName'], 'Sample Endpoint')
        self.assertEqual(response['event']['payload']['endpoints'][0]['capabilities'][0]['type'], 'AlexaInterface')
def handle_mode(name, event):
    endpoint_id = event['directive']['endpoint']['endpointId']
    correlation_token = event['directive']['header']['correlationToken']

    if name == "SetMode":
        mode = event['directive']['payload']['mode']
        if mode == 'LightMode.SingleColor':
            neo_mode = 1
        elif mode == 'LightMode.Knightrider':
            neo_mode = 2
        elif mode == 'LightMode.Starburst':
            neo_mode = 3
        elif mode == 'LightMode.SlowRainbow':
            neo_mode = 4
        elif mode == 'LightMode.FastRainbow':
            neo_mode = 5
        elif mode == 'LightMode.Emergency':
            neo_mode = 6

    elif name == "StateReport":
        mode = False

    if mode:
        state_sent = send_device_state(endpoint_id=endpoint_id,
                                       state='SetMode',
                                       value=neo_mode)
        if not state_sent:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        state_save = save_device_state(endpoint_id=endpoint_id,
                                       state='SetMode',
                                       value=mode)
        if not state_save:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach dynamo.'
                                 }).get()

    apcr = AlexaResponse(correlation_token=correlation_token)
    apcr.add_context_property(namespace=NAMESPACE_MODE,
                              name='mode',
                              value=mode,
                              endpoint_id=endpoint_id)
    return apcr.get()
def lambda_handler(event, context):
    print(f"---- Request ----\n{json.dumps(event)}")

    if context is not None:
        print(f"---- Context ----\n{context}")

    print(f"---- Env ----\n{os.environ}")

    if 'directive' not in event:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type':
                'INVALID_DIRECTIVE',
                'message':
                'Missing key: directive, Is the request a valid Alexa Directive?'
            })
        return send_response(aer.get())

    directive = event['directive']
    header = directive['header']

    payload_version = header['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'This skill only supports Smart Home API version 3'
            })
        return send_response(aer.get())

    name = header['name']
    namespace = header['namespace']

    if (namespace == NAMESPACE_DISCOVERY and name == REQUEST_DISCOVER):
        return send_response(handle_discovery(event))
    elif (namespace == NAMESPACE_CONTROL):
        return send_response(handle_control(name, event))
    elif (namespace == NAMESPACE_BRIGHTNESS):
        return send_response(handle_brightness(name, event))
    elif (namespace == NAMESPACE_MODE):
        return send_response(handle_mode(name, event))
    elif (namespace == NAMESPACE_COLOR):
        return send_response(handle_color(name, event))
    elif (namespace == NAMESPACE_AUTH and name == REQUEST_GRANT):
        return send_response(handle_auth(namespace))
    else:
        return send_response(handle_unexpected_info(namespace))
def discover_devices(request):
    """
    Discover the declared devices this handler supports
    """
    command = request['directive']['header']['name']
    if command == 'Discover':
        adr = AlexaResponse(namespace='Alexa.Discovery',
                            name='Discover.Response')
        capability_alexa = adr.create_payload_endpoint_capability()
        capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
            interface='Alexa.PowerController',
            supported=[{
                'name': 'powerState'
            }])
        for device in _DEVICES:
            adr.add_payload_endpoint(capabilities=[
                capability_alexa, capability_alexa_powercontroller
            ],
                                     **device)
        return success(adr.get())
def handle_color(name, event):
    endpoint_id = event['directive']['endpoint']['endpointId']
    correlation_token = event['directive']['header']['correlationToken']

    if name == "SetColor":
        color = event['directive']['payload']['color']
        neo_color = dict()
        neo_color["hue"] = round(color["hue"] * 65536 / 360)
        neo_color["saturation"] = round(color["saturation"] * 255)
        neo_color["brightness"] = round(color["brightness"] * 255)

    elif name == "StateReport":
        color = False

    if color:
        state_sent = send_device_state(endpoint_id=endpoint_id,
                                       state='SetColor',
                                       value=neo_color)
        if not state_sent:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        state_save = save_device_state(endpoint_id=endpoint_id,
                                       state='SetColor',
                                       value=color)
        if not state_save:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach dynamo.'
                                 }).get()

    apcr = AlexaResponse(correlation_token=correlation_token)
    apcr.add_context_property(namespace=NAMESPACE_COLOR,
                              name='color',
                              value=color,
                              endpoint_id=endpoint_id)
    return apcr.get()
def handle_brightness(name, event):
    endpoint_id = event['directive']['endpoint']['endpointId']
    correlation_token = event['directive']['header']['correlationToken']

    if name == "SetBrightness":
        brightness = event['directive']['payload']['brightness']
    elif name == "AdjustBrightness":
        brightness_delta = event['directive']['payload']['brightnessDelta']
        brightness = 50
    elif name == "StateReport":
        brightness = False

    if brightness:
        neo_brightness = round(brightness * 255 / 100)
        state_sent = send_device_state(endpoint_id=endpoint_id,
                                       state='SetBrightness',
                                       value=neo_brightness)
        if not state_sent:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        state_save = save_device_state(endpoint_id=endpoint_id,
                                       state='SetBrightness',
                                       value=brightness)
        if not state_save:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach dynamo.'
                                 }).get()

    apcr = AlexaResponse(correlation_token=correlation_token)
    apcr.add_context_property(namespace=NAMESPACE_BRIGHTNESS,
                              name='brightness',
                              value=brightness,
                              endpoint_id=endpoint_id)
    return apcr.get()
Example #17
0
    def process(self, request, client_id, client_secret, redirect_uri):
        print('LOG api_handler_directive.process -----')
        # print(json.dumps(request))

        response = None
        # Process an Alexa directive and route to the right namespace
        # Only process if there is an actual body to process otherwise return an ErrorResponse
        json_body = request['body']
        if json_body:
            json_object = json.loads(json_body)
            namespace = json_object['directive']['header']['namespace']

            if namespace == "Alexa":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']

                if name == 'ReportState':
                    # Get the User ID from the access_token
                    response_user_id = json.loads(
                        ApiAuth.get_user_id(token).read().decode('utf-8'))
                    result = dynamodb_aws.get_item(
                        TableName='SampleEndpointDetails',
                        Key={'EndpointId': {
                            'S': endpoint_id
                        }})
                    capabilities_string = self.get_db_value(
                        result['Item']['Capabilities'])
                    capabilities = json.loads(capabilities_string)
                    props = []
                    for c in capabilities:
                        if not 'properties' in c:
                            continue
                        retrievable = c['properties'].get('retrievable', False)
                        if retrievable:
                            props.append(c)
                    state = {}
                    try:
                        res = iot_data_aws.get_thing_shadow(
                            thingName=endpoint_id)
                        shadow = json.loads(res['payload'].read())
                        state = shadow['state']['desired']
                    except ClientError as e:
                        print('LOG ', e)

                    print('Sending StateReport for', response_user_id,
                          'on endpoint', endpoint_id)
                    statereport_response = AlexaResponse(
                        name='StateReport',
                        endpoint_id=endpoint_id,
                        correlation_token=correlation_token,
                        token=token)

                    for p in props:
                        key = p['properties']['supported'][0]['name']
                        if 'instance' in p:
                            key = p['instance'] + '.' + key
                        current_state = state.get(key,
                                                  DEFAULT_VAL[p['interface']])
                        if 'instance' in p:
                            statereport_response.add_context_property(
                                namespace=p['interface'],
                                name=p['properties']['supported'][0]['name'],
                                value=current_state,
                                instance=p['instance'])
                        else:
                            statereport_response.add_context_property(
                                namespace=p['interface'],
                                name=p['properties']['supported'][0]['name'],
                                value=current_state)

                    response = statereport_response.get()

            if namespace == "Alexa.Authorization":
                grant_code = json_object['directive']['payload']['grant'][
                    'code']
                grantee_token = json_object['directive']['payload']['grantee'][
                    'token']

                # Spot the default from the Alexa.Discovery sample. Use as a default for development.
                if grantee_token == 'access-token-from-skill':
                    user_id = "0"  # <- Useful for development
                    response_object = {
                        'access_token': 'INVALID',
                        'refresh_token': 'INVALID',
                        'token_type': 'Bearer',
                        'expires_in': 9000
                    }
                else:
                    # Get the User ID
                    response_user_id = json.loads(
                        ApiAuth.get_user_id(grantee_token).read().decode(
                            'utf-8'))
                    if 'error' in response_user_id:
                        print(
                            'ERROR api_handler_directive.process.authorization.user_id:',
                            response_user_id['error_description'])
                        return AlexaResponse(name='ErrorResponse',
                                             payload={
                                                 'type': 'INTERNAL_ERROR',
                                                 'message': response_user_id
                                             })

                    user_id = response_user_id['user_id']
                    print(
                        'LOG api_handler_directive.process.authorization.user_id:',
                        user_id)

                # Get the Access and Refresh Tokens
                api_auth = ApiAuth()
                print('grant_code', grant_code, 'client_id', client_id,
                      'client_secret', client_secret, 'redirect_uri',
                      redirect_uri)
                response_token = api_auth.get_access_token(
                    grant_code, client_id, client_secret, redirect_uri)
                response_token_string = response_token.read().decode('utf-8')
                print(
                    'LOG api_handler_directive.process.authorization.response_token_string:',
                    response_token_string)
                response_object = json.loads(response_token_string)

                if 'error' in response_object:
                    return AlexaResponse(name='ErrorResponse',
                                         payload={
                                             'type': 'INTERNAL_ERROR',
                                             'response_object': response_object
                                         })

                # Store the retrieved from the Authorization Server
                access_token = response_object['access_token']
                refresh_token = response_object['refresh_token']
                token_type = response_object['token_type']
                expires_in = response_object['expires_in']

                # Calculate expiration
                expiration_utc = datetime.utcnow() + timedelta(
                    seconds=(int(expires_in) - 5))

                # Store the User Information - This is useful for inspection during development
                table = boto3.resource('dynamodb').Table('SampleUsers')
                result = table.put_item(
                    Item={
                        'UserId':
                        user_id,
                        'GrantCode':
                        grant_code,
                        'GranteeToken':
                        grantee_token,
                        'AccessToken':
                        access_token,
                        'ClientId':
                        client_id,
                        'ClientSecret':
                        client_secret,
                        'ExpirationUTC':
                        expiration_utc.strftime("%Y-%m-%dT%H:%M:%S.00Z"),
                        'RedirectUri':
                        redirect_uri,
                        'RefreshToken':
                        refresh_token,
                        'TokenType':
                        token_type
                    })

                if result['ResponseMetadata']['HTTPStatusCode'] == 200:
                    print(
                        'LOG api_handler_directive.process.authorization.SampleUsers.put_item:',
                        result)
                    alexa_accept_grant_response = AlexaResponse(
                        namespace='Alexa.Authorization',
                        name='AcceptGrant.Response')
                    response = alexa_accept_grant_response.get()
                else:
                    error_message = 'Error creating User'
                    print('ERR api_handler_directive.process.authorization',
                          error_message)
                    alexa_error_response = AlexaResponse(name='ErrorResponse')
                    alexa_error_response.set_payload({
                        'type': 'INTERNAL_ERROR',
                        'message': error_message
                    })
                    response = alexa_error_response.get()

            if namespace == "Alexa.Cooking":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']
                if name == "SetCookingMode":
                    alexa_error_response = AlexaResponse(
                        endpoint_id=endpoint_id,
                        correlation_token=correlation_token,
                        token=token)
                    response = alexa_error_response.get()

            if namespace == "Alexa.Discovery":
                # Given the Access Token, get the User ID
                access_token = json_object['directive']['payload']['scope'][
                    'token']

                # Spot the default from the Alexa.Discovery sample. Use as a default for development.
                if access_token == 'access-token-from-skill':
                    print(
                        'WARN api_handler_directive.process.discovery.user_id: Using development user_id of 0'
                    )
                    user_id = "0"  # <- Useful for development
                else:
                    response_user_id = json.loads(
                        ApiAuth.get_user_id(access_token).read().decode(
                            'utf-8'))
                    if 'error' in response_user_id:
                        print(
                            'ERROR api_handler_directive.process.discovery.user_id: '
                            + response_user_id['error_description'])
                    user_id = response_user_id['user_id']
                    print(
                        'LOG api_handler_directive.process.discovery.user_id:',
                        user_id)

                adr = AlexaResponse(namespace='Alexa.Discovery',
                                    name='Discover.Response')

                # Get the list of endpoints to return for a User ID and add them to the response
                # Use the AWS IoT entries for state but get the discovery details from DynamoDB
                # Wanted to list by group name but that requires a second lookup for the details
                # iot_aws.list_things_in_thing_group(thingGroupName="Samples")
                list_response = iot_aws.list_things()

                # Get a list of sample things by the user_id attribute
                for thing in list_response['things']:
                    if 'user_id' in thing['attributes']:
                        if thing['attributes']['user_id'] == user_id:
                            # We have an endpoint thing!
                            endpoint_details = ApiHandlerEndpoint.EndpointDetails(
                            )
                            endpoint_details.id = str(thing['thingName'])
                            print(
                                'LOG api_handler_directive.process.discovery: Found:',
                                endpoint_details.id, 'for user:'******'SampleEndpointDetails',
                                Key={'EndpointId': {
                                    'S': endpoint_details.id
                                }})
                            capabilities_string = self.get_db_value(
                                result['Item']['Capabilities'])
                            endpoint_details.capabilities = json.loads(
                                capabilities_string)
                            endpoint_details.description = self.get_db_value(
                                result['Item']['Description'])
                            endpoint_details.display_categories = json.loads(
                                self.get_db_value(
                                    result['Item']['DisplayCategories']))
                            endpoint_details.friendly_name = self.get_db_value(
                                result['Item']['FriendlyName'])
                            endpoint_details.manufacturer_name = self.get_db_value(
                                result['Item']['ManufacturerName'])
                            endpoint_details.sku = self.get_db_value(
                                result['Item']['SKU'])
                            endpoint_details.user_id = self.get_db_value(
                                result['Item']['UserId'])

                            adr.add_payload_endpoint(
                                friendly_name=endpoint_details.friendly_name,
                                endpoint_id=endpoint_details.id,
                                capabilities=endpoint_details.capabilities,
                                display_categories=endpoint_details.
                                display_categories,
                                manufacturer_name=endpoint_details.
                                manufacturer_name)

                response = adr.get()

            if namespace == "Alexa.PowerController":
                name = json_object['directive']['header']['name']
                correlation_token = None
                if 'correlationToken' in json_object['directive']['header']:
                    correlation_token = json_object['directive']['header'][
                        'correlationToken']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']

                response_user_id = json.loads(
                    ApiAuth.get_user_id(token).read().decode('utf-8'))
                if 'error' in response_user_id:
                    print(
                        'ERROR api_handler_directive.process.power_controller.user_id: '
                        + response_user_id['error_description'])
                user_id = response_user_id['user_id']
                print(
                    'LOG api_handler_directive.process.power_controller.user_id:',
                    user_id)

                # Convert to a local stored state
                power_state_value = 'OFF' if name == "TurnOff" else 'ON'
                msg = {'state': {'desired': {'powerState': 'ON'}}}

                msg['state']['desired']['powerState'] = power_state_value
                mqtt_msg = json.dumps(msg)
                # Send the state to the Thing Shadow
                try:
                    response_update = iot_data_aws.update_thing_shadow(
                        thingName=endpoint_id, payload=mqtt_msg.encode())
                    print(
                        'LOG api_handler_directive.process.power_controller.response_update -----'
                    )
                    print(response_update)
                    alexa_response = AlexaResponse(
                        token=token,
                        correlation_token=correlation_token,
                        endpoint_id=endpoint_id)
                    alexa_response.add_context_property(
                        namespace='Alexa.PowerController',
                        name='powerState',
                        value=power_state_value)
                    alexa_response.add_context_property()
                    response = alexa_response.get()

                except ClientError as e:
                    print(
                        'ERR api_handler_directive.process.power_controller Exception:ClientError:',
                        e)
                    response = AlexaResponse(name='ErrorResponse',
                                             message=e).get()

            if namespace == "Alexa.ModeController":
                alexa_error_response = AlexaResponse(name='ErrorResponse')
                alexa_error_response.set_payload({
                    'type':
                    'INTERNAL_ERROR',
                    'message':
                    'Not Yet Implemented'
                })
                response = alexa_error_response.get()

            if namespace == "Alexa.RangeController":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                instance = json_object['directive']['header']['instance']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']

                result = dynamodb_aws.get_item(
                    TableName='SampleEndpointDetails',
                    Key={'EndpointId': {
                        'S': endpoint_id
                    }})
                capabilities_string = self.get_db_value(
                    result['Item']['Capabilities'])
                capabilities = json.loads(capabilities_string)

                for c in capabilities:
                    if 'instance' in c and c['instance'] == instance:
                        MIN_VAL = c['configuration']['supportedRange'][
                            'minimumValue']
                        MAX_VAL = c['configuration']['supportedRange'][
                            'maximumValue']
                        PREC = c['configuration']['supportedRange'][
                            'precision']
                        break

                alexa_response = AlexaResponse(
                    endpoint_id=endpoint_id,
                    correlation_token=correlation_token,
                    token=token)
                value = 0
                if name == "AdjustRangeValue":
                    range_value_delta = json_object['directive']['payload'][
                        'rangeValueDelta']
                    range_value_delta_default = json_object['directive'][
                        'payload']['rangeValueDeltaDefault']
                    reported_range_value = 0

                    # Check to see if we need to use the delta default value (The user did not give a precision)
                    if range_value_delta_default:
                        range_value_delta = PREC

                    # Lookup the existing value of the endpoint by endpoint_id and limit ranges as appropriate - for this sample, expecting 1-6
                    try:
                        response = iot_data_aws.get_thing_shadow(
                            thingName=endpoint_id)
                        payload = json.loads(response['payload'].read())
                        reported_range_value = payload['state']['reported'][
                            instance + '.rangeValue']
                        print(
                            'LOG api_handler_directive.process.range_controller.range_value:',
                            reported_range_value)
                    except ClientError as e:
                        print(e)
                    except KeyError as errorKey:
                        print('Could not find key:', errorKey)

                    new_range_value = reported_range_value + range_value_delta

                    value = max(min(new_range_value, MAX_VAL), MIN_VAL)

                if name == "SetRangeValue":
                    range_value = json_object['directive']['payload'][
                        'rangeValue']

                    value = max(min(range_value, MAX_VAL), MIN_VAL)
                    alexa_response.add_context_property(
                        namespace='Alexa.RangeController',
                        name='rangeValue',
                        value=value)

                # Update the Thing Shadow
                msg = {'state': {'desired': {}}}
                # NOTE: The instance is used to keep the stored value unique
                msg['state']['desired'][instance + '.rangeValue'] = value
                mqtt_msg = json.dumps(msg)
                response_update = iot_data_aws.update_thing_shadow(
                    thingName=endpoint_id, payload=mqtt_msg.encode())
                print(
                    'LOG api_handler_directive.process.range_controller.response_update -----'
                )
                print(response_update)

                # Send back the response
                response = alexa_response.get()

            if namespace == "Alexa.ToggleController":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                instance = json_object['directive']['header']['instance']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']

                # Convert to a local stored state
                toggle_state_value = 'OFF' if name == "TurnOff" else 'ON'
                state_name = instance + '.state'
                msg = {'state': {'desired': {state_name: 'ON'}}}
                msg['state']['desired'][state_name] = toggle_state_value
                mqtt_msg = json.dumps(msg)
                # Send the state to the Thing Shadow
                try:
                    response_update = iot_data_aws.update_thing_shadow(
                        thingName=endpoint_id, payload=mqtt_msg.encode())
                    print(
                        'LOG api_handler_directive.process.toggle_controller.response_update -----'
                    )
                    print(response_update)
                    alexa_response = AlexaResponse(
                        token=token,
                        correlation_token=correlation_token,
                        endpoint_id=endpoint_id)
                    alexa_response.add_context_property(
                        namespace='Alexa.ToggleController',
                        name='toggleState',
                        instance=instance,
                        value=toggle_state_value)
                    alexa_response.add_context_property()
                    response = alexa_response.get()

                except ClientError as e:
                    print(
                        'ERR api_handler_directive.process.toggle_controller Exception:ClientError:',
                        e)
                    response = AlexaResponse(name='ErrorResponse',
                                             message=e).get()

        else:
            alexa_error_response = AlexaResponse(name='ErrorResponse')
            alexa_error_response.set_payload({
                'type': 'INTERNAL_ERROR',
                'message': 'Empty Body'
            })
            response = alexa_error_response.get()

        if response is None:
            # response set to None indicates an unhandled directive, review the logs
            alexa_error_response = AlexaResponse(name='ErrorResponse')
            alexa_error_response.set_payload({
                'type':
                'INTERNAL_ERROR',
                'message':
                'Empty Response: No response processed. Unhandled Directive.'
            })
            response = alexa_error_response.get()

        print('LOG api_handler_directive.process.response -----')
        print(json.dumps(response))
        return response
 def test_response(self):
     response = AlexaResponse().get()
     
     self.assertEqual(response['event']['header']['namespace'], 'Alexa')
     self.assertEqual(response['event']['header']['name'], 'Response')
    def process(self, request, client_id, client_secret, redirect_uri):
        print('LOG directive.process.request:', request)

        response = None
        # Process an Alexa directive and route to the right namespace
        # Only process if there is an actual body to process otherwise return an ErrorResponse
        json_body = request['body']
        if json_body:
            json_object = json.loads(json_body)
            namespace = json_object['directive']['header']['namespace']

            if namespace == "Alexa":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']
                if name == 'ReportState':
                    # TODO Get the User ID from the access_token
                    # TODO Lookup the endpoint and get state
                    print('Sending StateReport for endpoint', endpoint_id)
                    alexa_reportstate_response = AlexaResponse(
                        name='StateReport',
                        endpoint_id=endpoint_id,
                        correlation_token=correlation_token)
                    response = alexa_reportstate_response.get()

            if namespace == "Alexa.Authorization":
                grant_code = json_object['directive']['payload']['grant'][
                    'code']
                grantee_token = json_object['directive']['payload']['grantee'][
                    'token']

                # Spot the default from the Alexa.Discovery sample. Use as a default for development.
                if grantee_token == 'access-token-from-skill':
                    user_id = "0"  # <- Useful for development
                    response_object = {
                        'access_token': 'INVALID',
                        'refresh_token': 'INVALID',
                        'token_type': 'Bearer',
                        'expires_in': 9000
                    }
                else:
                    # Get the User ID
                    response_user_id = json.loads(
                        ApiAuth.get_user_id(grantee_token).read().decode(
                            'utf-8'))
                    if 'error' in response_user_id:
                        print('ERROR directive.process.authorization.user_id:',
                              response_user_id['error_description'])
                    user_id = response_user_id['user_id']
                    print('LOG directive.process.authorization.user_id:',
                          user_id)

                    # Get the Access and Refresh Tokens
                    api_auth = ApiAuth()
                    response_token = api_auth.get_access_token(
                        grant_code, client_id, client_secret, redirect_uri)
                    response_token_string = response_token.read().decode(
                        'utf-8')
                    print(
                        'LOG directive.process.authorization.response_token_string:',
                        response_token_string)
                    response_object = json.loads(response_token_string)

                # Store the retrieved from the Authorization Server
                access_token = response_object['access_token']
                refresh_token = response_object['refresh_token']
                token_type = response_object['token_type']
                expires_in = response_object['expires_in']

                # Calculate expiration
                expiration_utc = datetime.utcnow() + timedelta(
                    seconds=(int(expires_in) - 5))

                # Store the User Information - This is useful for inspection during development
                table = boto3.resource('dynamodb').Table('SampleUsers')
                result = table.put_item(
                    Item={
                        'UserId':
                        user_id,
                        'GrantCode':
                        grant_code,
                        'GranteeToken':
                        grantee_token,
                        'AccessToken':
                        access_token,
                        'ClientId':
                        client_id,
                        'ClientSecret':
                        client_secret,
                        'ExpirationUTC':
                        expiration_utc.strftime("%Y-%m-%dT%H:%M:%S.00Z"),
                        'RedirectUri':
                        redirect_uri,
                        'RefreshToken':
                        refresh_token,
                        'TokenType':
                        token_type
                    })

                if result['ResponseMetadata']['HTTPStatusCode'] == 200:
                    print(
                        'LOG directive.process.authorization.SampleUsers.put_item:',
                        result)
                    alexa_accept_grant_response = AlexaResponse(
                        namespace='Alexa.Authorization',
                        name='AcceptGrant.Response')
                    response = alexa_accept_grant_response.get()

                else:
                    error_message = 'Error creating User'
                    print('ERR directive.process.authorization', error_message)
                    alexa_error_response = AlexaResponse(name='ErrorResponse')
                    alexa_error_response.set_payload({
                        'type': 'INTERNAL_ERROR',
                        'message': error_message
                    })
                    response = alexa_error_response.get()

            if namespace == "Alexa.Cooking":
                name = json_object['directive']['header']['name']
                correlation_token = json_object['directive']['header'][
                    'correlationToken']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']
                if name == "SetCookingMode":
                    alexa_error_response = AlexaResponse(
                        endpoint_id=endpoint_id,
                        correlation_token=correlation_token,
                        token=token)
                    response = alexa_error_response.get()

            if namespace == "Alexa.Discovery":
                # Given the Access Token, get the User ID
                access_token = json_object['directive']['payload']['scope'][
                    'token']

                # Spot the default from the Alexa.Discovery sample. Use as a default for development.
                if access_token == 'access-token-from-skill':
                    print(
                        'WARN directive.process.discovery.user_id: Using development user_id of 0'
                    )
                    user_id = "0"  # <- Useful for development
                else:
                    response_user_id = json.loads(
                        ApiAuth.get_user_id(access_token).read().decode(
                            'utf-8'))
                    if 'error' in response_user_id:
                        print('ERROR directive.process.discovery.user_id: ' +
                              response_user_id['error_description'])
                    user_id = response_user_id['user_id']
                    print('LOG directive.process.discovery.user_id:', user_id)

                alexa_discover_response = AlexaDiscoverResponse(json_object)

                # Get the list of endpoints to return for a User ID and add them to the response
                # Use the AWS IoT entries for state but get the discovery details from DynamoDB
                # HACK Boto3 1.4.8 attributeName and attributeValue stopped working, raw list_things() works however
                # Not Working: list_response = iot_aws.list_things(attributeName='user_id', attributeValue=user_id)
                list_response = iot_aws.list_things()
                for thing in list_response['things']:
                    if thing['attributes']['user_id'] == user_id:
                        endpoint_details = ApiHandlerEndpoint.EndpointDetails()
                        endpoint_details.id = str(
                            thing['thingName']
                        )  # Add attribute endpoint_id to free thingName?
                        print('LOG directive.process.discovery: Found:',
                              endpoint_details.id, 'for user:'******'SampleEndpointDetails',
                            Key={'EndpointId': {
                                'S': endpoint_details.id
                            }})
                        capabilities_string = self.get_db_value(
                            result['Item']['Capabilities'])
                        endpoint_details.capabilities = json.loads(
                            capabilities_string)
                        endpoint_details.description = self.get_db_value(
                            result['Item']['Description'])
                        endpoint_details.display_categories = json.loads(
                            self.get_db_value(
                                result['Item']['DisplayCategories']))
                        endpoint_details.friendly_name = self.get_db_value(
                            result['Item']['FriendlyName'])
                        endpoint_details.manufacturer_name = self.get_db_value(
                            result['Item']['ManufacturerName'])
                        endpoint_details.sku = self.get_db_value(
                            result['Item']['SKU'])
                        endpoint_details.user_id = self.get_db_value(
                            result['Item']['UserId'])
                        alexa_discover_response.add_endpoint(endpoint_details)

                response = alexa_discover_response.get_response()

            if namespace == "Alexa.PowerController":
                name = json_object['directive']['header']['name']
                correlation_token = None
                if 'correlationToken' in json_object['directive']['header']:
                    correlation_token = json_object['directive']['header'][
                        'correlationToken']
                token = json_object['directive']['endpoint']['scope']['token']
                endpoint_id = json_object['directive']['endpoint'][
                    'endpointId']

                response_user_id = json.loads(
                    ApiAuth.get_user_id(token).read().decode('utf-8'))
                if 'error' in response_user_id:
                    print(
                        'ERROR directive.process.power_controller.user_id: ' +
                        response_user_id['error_description'])
                user_id = response_user_id['user_id']
                print('LOG directive.process.power_controller.user_id',
                      user_id)

                # Convert to a local stored state
                power_state_value = 'OFF' if name == "TurnOff" else 'ON'
                try:
                    # Send the state to the Thing
                    response_update = iot_aws.update_thing(
                        thingName=endpoint_id,
                        attributePayload={
                            'attributes': {
                                'state': power_state_value,
                                'user_id': user_id
                            }
                        })
                    print(
                        'LOG directive.process.power_controller.response_update:',
                        response_update)
                    alexa_power_controller_response = AlexaResponse(
                        namespace='Alexa.PowerController',
                        name=name,
                        token=token,
                        correlation_token=correlation_token,
                        endpoint_id=endpoint_id)
                    response = alexa_power_controller_response.get()
                except ClientError as e:
                    response = AlexaResponse(name='ErrorResponse',
                                             message=e).get()

        else:
            response = AlexaResponse(name='ErrorResponse').get()

        if response is None:
            # response set to None indicates an unhandled directive, review the logs
            response = AlexaResponse(
                name='ErrorResponse',
                message='Empty Response: No response processed').get()
        # else:
        # TODO Validate the Response once the schema is updated
        # if not self.validate_response(response):
        #     response = AlexaError(message='Failed to validate message against the schema').get_response()

        # print('LOG directive.process.response', response)
        return json.dumps(response)
 def test_response_error(self):
     payload_error = {"type": "INVALID_SOMETHING", "message": "ERROR_MESSAGE"}
     response = AlexaResponse(name="ErrorResponse", payload=payload_error).get()
     
     self.assertEqual(response['event']['header']['name'], 'ErrorResponse')
 def test_response_cookie(self):
     response = AlexaResponse(cookie={"key": "value"}).get()
     
     self.assertEqual(response['event']['endpoint']['cookie']['key'], 'value')
def lambda_handler(request, context):

    # Dump the request for logging - check the CloudWatch logs
    print('lambda_handler request  -----')
    print(json.dumps(request))

    if context is not None:
        print('lambda_handler context  -----')
        print(context)

    # Validate we have an Alexa directive
    if 'directive' not in request:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type':
                'INVALID_DIRECTIVE',
                'message':
                'Missing key: directive, Is the request a valid Alexa Directive?'
            })
        return send_response(aer.get())

    # Check the payload version
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'This skill only supports Smart Home API version 3'
            })
        return send_response(aer.get())

    # Crack open the request and see what is being requested
    name = request['directive']['header']['name']
    namespace = request['directive']['header']['namespace']

    print('Name:' + name)
    print('Namespace:' + namespace)

    # Handle the incoming request from Alexa based on the namespace

    if namespace == 'Alexa.Authorization':

        if name == 'AcceptGrant':

            # Note: This sample accepts any grant request
            # In your implementation you would use the code and token to get and store access tokens
            grant_code = request['directive']['payload']['grant']['code']
            grantee_token = request['directive']['payload']['grantee']['token']
            aar = AlexaResponse(namespace='Alexa.Authorization',
                                name='AcceptGrant.Response')
            return send_response(aar.get())

    if namespace == 'Alexa.Discovery':

        if name == 'Discover':

            adr = AlexaResponse(namespace='Alexa.Discovery',
                                name='Discover.Response')

            capability_alexa = adr.create_payload_endpoint_capability()

            capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
                interface='Alexa.PowerController',
                supported=[{
                    'name': 'powerState'
                }])

            capability_alexa_temperaturesensor = adr.create_payload_endpoint_capability(
                interface='Alexa.TemperatureSensor',
                supported=[{
                    'name': 'temperature'
                }],
                retrievable='true',
                proactively_reported='true',
            )

            capability_alexa_endpointhealth = adr.create_payload_endpoint_capability(
                interface='Alexa.EndpointHealth',
                supported=[{
                    'name': 'connectivity'
                }],
                proactively_reported='true',
                retrievable='true')

            #    adr.add_payload_endpoint(
            #        friendly_name='Termostato Sala',
            #        endpoint_id='temperaturesensor-001',
            #        description='Termostato Sala',
            #        display_categories=["TEMPERATURE_SENSOR"],
            #        manufacturer_name = 'myself manufacter',
            #        capabilities=[capability_alexa, capability_alexa_temperaturesensor, capability_alexa_endpointhealth ])

            #    adr.add_payload_endpoint(
            #        friendly_name='Termostato Cucina',
            #        endpoint_id='temperaturesensor-002',
            #        description='Termostato Cucina',
            #        display_categories=["TEMPERATURE_SENSOR"],
            #        manufacturer_name = 'myself manufacter',
            #        capabilities=[capability_alexa, capability_alexa_temperaturesensor, capability_alexa_endpointhealth ])

            adr.add_payload_endpoint(friendly_name='Luce 01',
                                     endpoint_id='light-001',
                                     description='Luce 01',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 02',
                                     endpoint_id='light-002',
                                     description='Luce 02',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 03',
                                     endpoint_id='light-003',
                                     description='Luce 03',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 04',
                                     endpoint_id='light-004',
                                     description='Luce 04',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 05',
                                     endpoint_id='light-005',
                                     description='Luce 05',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 06',
                                     endpoint_id='light-006',
                                     description='Luce 06',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 07',
                                     endpoint_id='light-007',
                                     description='Luce 07',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Luce 08',
                                     endpoint_id='light-008',
                                     description='Luce 08',
                                     display_categories=["LIGHT"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            adr.add_payload_endpoint(friendly_name='Cancellino',
                                     endpoint_id='gate-001',
                                     description='Cancellino',
                                     display_categories=["DOOR"],
                                     manufacturer_name='myself manufacter',
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])

            return send_response(adr.get())

    if namespace == 'Alexa':

        if name == 'ReportState':

            print('Richiesta tipo ReportState  -----')

            # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
            endpoint_id = request['directive']['endpoint']['endpointId']

            print('ENDPOINT ID: ' + endpoint_id)

            correlation_token = request['directive']['header'][
                'correlationToken']
            token = request['directive']['endpoint']['scope']['token']

            print('Correlation_Token: ' + correlation_token)
            print('Token: ' + token)

            apcr = AlexaResponse(name='StateReport',
                                 endpoint_id=endpoint_id,
                                 correlation_token=correlation_token,
                                 token=token)

            if (endpoint_id == 'temperaturesensor-001'):

                apcr.add_context_property(namespace='Alexa.TemperatureSensor',
                                          name='temperature',
                                          value={
                                              'value': '19.9',
                                              'scale': 'CELSIUS'
                                          })

            elif (endpoint_id == 'temperaturesensor-002'):

                apcr.add_context_property(namespace='Alexa.TemperatureSensor',
                                          name='temperature',
                                          value={
                                              'value': '22.3',
                                              'scale': 'CELSIUS'
                                          })

            return send_response(apcr.get())

    if namespace == 'Alexa.PowerController' or namespace == 'Alexa.ToogleController':

        print('Richiesta tipo PowerController  -----')
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']

        power_state_value = 'OFF' if name == 'TurnOff' else 'ON'

        correlation_token = request['directive']['header']['correlationToken']

        # Check for an error when setting the state
        state_set = set_device_state(endpoint_id=endpoint_id,
                                     state='powerState',
                                     value=power_state_value)

        if not state_set:

            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type':
                                     'ENDPOINT_UNREACHABLE',
                                     'message':
                                     'Unable to reach endpoint database.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PowerController',
                                  name='powerState',
                                  value=power_state_value)

        return send_response(apcr.get())
    def create(self, request):
        print('LOG event.create.request -----')
        print(request)

        try:
            json_object = json.loads(request['body'])

            # Transpose the Endpoint Cloud Event into an Alexa Event Gateway Event

            # Get the common information from the body of the request
            event_type = json_object['event'][
                'type']  # Expect AddOrUpdateReport, ChangeReport, DeleteReport
            endpoint_user_id = json_object['event']['endpoint'][
                'userId']  # Expect a Profile
            endpoint_id = json_object['event']['endpoint'][
                'id']  # Expect a valid AWS IoT Thing Name

            # Get the Access Token
            token = self.get_user_info(endpoint_user_id)

            # Build a default response
            response = AlexaResponse(name='ErrorResponse',
                                     message="No valid event type")

            if event_type == 'AddOrUpdateReport':
                # Get the additional information from the body of the request
                endpoint_friendly_name = json_object['event']['endpoint'][
                    'friendlyName']  # Expect a valid string friendly name
                endpoint_capabilities = json_object['event']['endpoint'][
                    'capabilities']  # Expect a valid AWS IoT Thing Name
                sku = json_object['event']['endpoint'][
                    'sku']  # Expect a meaningful type, ex: SW00

                # From the SKU, get the information for the device and combine it in the payload
                endpoint_sku_details = self.get_sku_details(sku)
                payload = {
                    'endpoints': [{
                        'endpointId':
                        endpoint_id,
                        'friendlyName':
                        endpoint_friendly_name,
                        'description':
                        endpoint_sku_details['description'],
                        'manufacturerName':
                        endpoint_sku_details['manufacturer_name'],
                        'displayCategories':
                        endpoint_sku_details['display_categories'],
                        'capabilities':
                        endpoint_capabilities
                    }],
                    'scope': {
                        'type': 'BearerToken',
                        'token': token
                    }
                }

                # Send an event to Alexa to add/update the endpoint
                response = self.send_event('Alexa.Discovery',
                                           'AddOrUpdateReport', endpoint_id,
                                           token, payload)

            if event_type == 'ChangeReport':
                try:
                    state = json_object['event']['endpoint'][
                        'state']  # Expect a string, ex: powerState
                    state_value = json_object['event']['endpoint'][
                        'value']  # Expect string or JSON

                    # Update the IoT Thing Shadow state
                    msg = {'state': {'desired': {state: state_value}}}
                    mqtt_msg = json.dumps(msg)
                    result = iot_data_aws.update_thing_shadow(
                        thingName=endpoint_id, payload=mqtt_msg.encode())
                    print(
                        'LOG event.create.iot_aws.update_thing_shadow.result -----'
                    )
                    print(result)

                    # Update Alexa with an Event Update
                    if endpoint_user_id == '0':
                        print('LOG Event: Not sent for user_id of 0')
                    else:
                        payload = {
                            'change': {
                                'cause': {
                                    'type': 'PHYSICAL_INTERACTION'
                                },
                                "properties": [
                                    AlexaResponse.create_context_property(
                                        name=state, value=state_value)
                                ]
                            }
                        }
                        print('LOG Event: Sending event')
                        response = self.send_event('Alexa', 'ChangeReport',
                                                   endpoint_id, token, payload)

                except ClientError as e:
                    alexa_response = AlexaResponse(name='ErrorResponse',
                                                   message=e,
                                                   payload={
                                                       'type':
                                                       'INTERNAL_ERROR',
                                                       'message': e
                                                   })
                    return alexa_response.get()

            if event_type == 'DeleteReport':
                # Send an event to Alexa to delete the endpoint
                payload = {
                    'endpoints': [{
                        'endpointId': endpoint_id
                    }],
                    "scope": {
                        "type": "BearerToken",
                        "token": token
                    }
                }
                response = self.send_event('Alexa.Discovery', 'DeleteReport',
                                           endpoint_id, token, payload)

            result = response.read().decode('utf-8')
            print('LOG event.create.result -----')
            print(result)
            return result

        except KeyError as key_error:
            return "KeyError: " + str(key_error)
def lambda_handler(request, context):

    # Dump the request for logging - check the CloudWatch logs
    print('lambda_handler request  -----')
    print(json.dumps(request))

    if context is not None:
        print('lambda_handler context  -----')
        print(context)

    # Validate we have an Alexa directive
    if 'directive' not in request:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type':
                'INVALID_DIRECTIVE',
                'message':
                'Missing key: directive, Is the request a valid Alexa Directive?'
            })
        return send_response(aer.get())

    # Check the payload version
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'This skill only supports Smart Home API version 3'
            })
        return send_response(aer.get())

    # Crack open the request and see what is being requested
    name = request['directive']['header']['name']
    namespace = request['directive']['header']['namespace']

    # Handle the incoming request from Alexa based on the namespace

    if namespace == 'Alexa.Authorization':
        if name == 'AcceptGrant':
            # Note: This sample accepts any grant request
            # In your implementation you would use the code and token to get and store access tokens
            grant_code = request['directive']['payload']['grant']['code']
            grantee_token = request['directive']['payload']['grantee']['token']
            aar = AlexaResponse(namespace='Alexa.Authorization',
                                name='AcceptGrant.Response')
            return send_response(aar.get())

    if namespace == 'Alexa.Discovery':
        if name == 'Discover':
            adr = AlexaResponse(namespace='Alexa.Discovery',
                                name='Discover.Response')
            capability_alexa = adr.create_payload_endpoint_capability()
            capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
                interface='Alexa.PowerController',
                supported=[{
                    'name': 'powerState'
                }])
            adr.add_payload_endpoint(endpoint_id='LED',
                                     friendly_name='LED',
                                     description='これはただのLEDです。',
                                     display_categories=['LIGHT'],
                                     capabilities=[
                                         capability_alexa,
                                         capability_alexa_powercontroller
                                     ])
            return send_response(adr.get())

    if namespace == 'Alexa.PowerController':
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']
        power_state_value = 'OFF' if name == 'TurnOff' else 'ON'
        correlation_token = request['directive']['header']['correlationToken']

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PowerController',
                                  name='powerState',
                                  value=power_state_value)

        # Update Thing Shadow Desired Value
        update_thing_shadow("led",
                            False if power_state_value == 'OFF' else True)

        return send_response(apcr.get())
Example #25
0
def lambda_handler(request, context):

    # Dump the request for logging - check the CloudWatch logs
    print('lambda_handler request  -----')
    print(json.dumps(request))

    if context is not None:
        print('lambda_handler context  -----')
        print(context)

    # Validate we have an Alexa directive
    if 'directive' not in request:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={'type': 'INVALID_DIRECTIVE',
                     'message': 'Missing key: directive, Is the request a valid Alexa Directive?'})
        return send_response(aer.get())

    # Check the payload version
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={'type': 'INTERNAL_ERROR',
                     'message': 'This skill only supports Smart Home API version 3'})
        return send_response(aer.get())

    # Crack open the request and see what is being requested
    name = request['directive']['header']['name']
    namespace = request['directive']['header']['namespace']

    # Handle the incoming request from Alexa based on the namespace

    if namespace == 'Alexa.Authorization':
        if name == 'AcceptGrant':
            # Note: This sample accepts any grant request
            # In your implementation you would use the code and token to get and store access tokens
            grant_code = request['directive']['payload']['grant']['code']
            grantee_token = request['directive']['payload']['grantee']['token']
            aar = AlexaResponse(namespace='Alexa.Authorization', name='AcceptGrant.Response')
            return send_response(aar.get())

    if namespace == 'Alexa.Discovery':
        if name == 'Discover':
            adr = AlexaResponse(namespace='Alexa.Discovery', name='Discover.Response')
            capability_alexa = adr.create_payload_endpoint_capability()
            capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
                interface='Alexa.PowerController',
                supported=[{'name': 'powerState'}])
            adr.add_payload_endpoint(
                friendly_name='Sample Switch',
                endpoint_id='sample-switch-01',
                capabilities=[capability_alexa, capability_alexa_powercontroller])
            return send_response(adr.get())

    if namespace == 'Alexa.PowerController':
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']
        power_state_value = 'OFF' if name == 'TurnOff' else 'ON'
        correlation_token = request['directive']['header']['correlationToken']

        # Check for an error when setting the state
        state_set = set_device_state(endpoint_id=endpoint_id, state='powerState', value=power_state_value)
        if not state_set:
            return AlexaResponse(
                name='ErrorResponse',
                payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()

        # Check for an error when setting TurnOn/TurnOff time
        if power_state_value == 'ON':
            TurnOn_set = set_device_time(endpoint_id=endpoint_id, state='TurnOnTime', value=get_seconds_timestamp())
            if not TurnOn_set:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()
            global turned_on
            turned_on = get_seconds_timestamp()
            time.sleep(random.uniform(1.500,2.500))
            TurnOff_set = set_device_state(endpoint_id=endpoint_id, state='powerState', value='OFF')
            print("turnedoff")
            # if not TurnOff_set:
            #     return AlexaResponse(
            #         name='ErrorResponse',
            #         payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()
        if power_state_value == 'OFF':
            TurnOff_set = set_device_time(endpoint_id=endpoint_id, state='TurnOffTime', value=get_seconds_timestamp())
            if not TurnOff_set:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()
            global turned_off
            turned_off = get_seconds_timestamp()
            uptime_length = get_uptime_length(turned_on, turned_off)
            last_uptime_length = set_device_time(endpoint_id=endpoint_id, state='LastUptimeLength', value=uptime_length)
            if not last_uptime_length:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()
            add_value_to_file(uptime_length)

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PowerController', name='powerState', value=power_state_value)
        return send_response(apcr.get())
def handle_discovery(event):
    adr = AlexaResponse(namespace=NAMESPACE_DISCOVERY, name=RESPONSE_DISCOVER)
    capability_alexa = adr.create_payload_endpoint_capability()
    capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
        interface=NAMESPACE_CONTROL, supported=[{
            'name': 'powerState'
        }])

    capability_alexa_brightnesscontroller = adr.create_payload_endpoint_capability(
        interface=NAMESPACE_BRIGHTNESS, supported=[{
            'name': 'brightness'
        }])

    capability_alexa_colorcontroller = adr.create_payload_endpoint_capability(
        interface=NAMESPACE_COLOR, supported=[{
            'name': 'color'
        }])

    capability_alexa_modecontroller = adr.create_payload_endpoint_capability(
        interface=NAMESPACE_MODE, supported=[{
            'name': 'mode'
        }])

    capability_alexa_modecontroller['instance'] = 'CharlotteLight.LightMode'
    capability_alexa_modecontroller['capabilityResources'] = {
        "friendlyNames": [{
            "@type": "text",
            "value": {
                "text": "mode",
                "locale": "en-GB"
            }
        }, {
            "@type": "text",
            "value": {
                "text": "light mode",
                "locale": "en-GB"
            }
        }, {
            "@type": "text",
            "value": {
                "text": "pattern",
                "locale": "en-GB"
            }
        }, {
            "@type": "text",
            "value": {
                "text": "color mode",
                "locale": "en-GB"
            }
        }]
    }

    capability_alexa_modecontroller['configuration'] = {
        "ordered":
        False,
        "supportedModes": [{
            "value": "LightMode.SingleColor",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "normal",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "single color",
                        "locale": "en-GB"
                    }
                }]
            }
        }, {
            "value": "LightMode.Knightrider",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "knightrider",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "night rider",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "scroll",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "cylon",
                        "locale": "en-GB"
                    }
                }]
            }
        }, {
            "value": "LightMode.Starburst",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "stars",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "starburst",
                        "locale": "en-GB"
                    }
                }]
            }
        }, {
            "value": "LightMode.SlowRainbow",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "rainbow",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "slow rainbow",
                        "locale": "en-GB"
                    }
                }]
            }
        }, {
            "value": "LightMode.FastRainbow",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "fast rainbow",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "chase rainbow",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "cinema chase rainbow",
                        "locale": "en-GB"
                    }
                }]
            }
        }, {
            "value": "LightMode.Emergency",
            "modeResources": {
                "friendlyNames": [{
                    "@type": "text",
                    "value": {
                        "text": "emergency",
                        "locale": "en-GB"
                    }
                }, {
                    "@type": "text",
                    "value": {
                        "text": "emergency lights",
                        "locale": "en-GB"
                    }
                }]
            }
        }]
    }

    capability_alexa_scenecontroller = adr.create_payload_endpoint_capability(
        interface=NAMESPACE_SCENE)

    adr.add_payload_endpoint(friendly_name='Charlotte Light',
                             endpoint_id='charlotte-light-01',
                             manufacturer_name='Larssen Inc',
                             description='NeoPixel Light',
                             display_categories=["LIGHT"],
                             capabilities=[
                                 capability_alexa,
                                 capability_alexa_powercontroller,
                                 capability_alexa_brightnesscontroller,
                                 capability_alexa_colorcontroller,
                                 capability_alexa_modecontroller,
                                 capability_alexa_scenecontroller
                             ])
    return adr.get()
def handle_auth(event):
    grant_code = event['directive']['payload']['grant']['code']
    grantee_token = event['directive']['payload']['grantee']['token']
    aar = AlexaResponse(namespace=NAMESPACE_AUTH, name=RESPONSE_GRANT)
    return aar.get()
def handle_unexpected_info(namespace):
    return AlexaResponse(name='ErrorResponse',
                         payload={
                             'type': 'INVALID_DIRECTIVE',
                             'message': f'Unknown namespace: {namespace}'
                         }).get()
Example #29
0
def lambda_handler(request, context):

    # Dump the request for logging - check the CloudWatch logs
    logger.debug('lambda_handler request  -----')
    logger.debug(json.dumps(request))

    if context is not None:
        logger.debug('lambda_handler context  -----')
        logger.debug(context)

    # Validate we have an Alexa directive
    if 'directive' not in request:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type':
                'INVALID_DIRECTIVE',
                'message':
                'Missing key: directive, Is the request a valid Alexa Directive?'
            })
        return send_response(aer.get())

    # Check the payload version
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'This skill only supports Smart Home API version 3'
            })
        return send_response(aer.get())

    # Crack open the request and see what is being requested
    name = request['directive']['header']['name']
    namespace = request['directive']['header']['namespace']

    # Handle the incoming request from Alexa based on the namespace

    if namespace == 'Alexa.Authorization':
        if name == 'AcceptGrant':
            # Note: This sample accepts any grant request
            # In your implementation you would use the code and token to get and store access tokens
            grant_code = request['directive']['payload']['grant']['code']
            grantee_token = request['directive']['payload']['grantee']['token']
            aar = AlexaResponse(namespace='Alexa.Authorization',
                                name='AcceptGrant.Response')
            return send_response(aar.get())

    if namespace == 'Alexa.Discovery':
        if name == 'Discover':
            adr = AlexaResponse(namespace='Alexa.Discovery',
                                name='Discover.Response')
            capability_alexa = adr.create_payload_endpoint_capability()
            capability_alexa_powercontroller = adr.create_payload_endpoint_capability(
                interface='Alexa.PowerController',
                supported=[{
                    'name': 'powerState'
                }],
                proactively_reported=False,
                retrievable=False)
            capability_alexa_colorcontroller = adr.create_payload_endpoint_capability(
                interface='Alexa.ColorController',
                supported=[{
                    'name': 'color'
                }],
                proactively_reported=False,
                retrievable=False)
            adr.add_payload_endpoint(
                friendly_name=
                'Den Lights',  # TODO remove hardcoded friendly name
                endpoint_id=
                'thomas-den-lights',  # TODO removed hardcoded endpoint_id
                capabilities=[
                    capability_alexa, capability_alexa_powercontroller,
                    capability_alexa_colorcontroller
                ])
            return send_response(adr.get())

    if namespace == 'Alexa.PowerController':
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']
        power_state_value = 'OFF' if name == 'TurnOff' else 'ON'
        correlation_token = request['directive']['header']['correlationToken']

        # Check for an error when setting the state
        state_set = set_device_state(endpoint_id=endpoint_id,
                                     state='powerState',
                                     value=power_state_value)
        if not state_set:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type':
                                     'ENDPOINT_UNREACHABLE',
                                     'message':
                                     'Unable to reach endpoint database.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PowerController',
                                  name='powerState',
                                  value=power_state_value)
        return send_response(apcr.get())

    if namespace == 'Alexa.ColorController' and name == 'SetColor':
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']
        correlation_token = request['directive']['header']['correlationToken']

        # Check for an error when setting the state
        color_set = set_color_state(
            endpoint_id=endpoint_id,
            state='color',
            value=request['directive']['payload']['color'])
        if not color_set:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type':
                                     'ENDPOINT_UNREACHABLE',
                                     'message':
                                     'Unable to reach endpoint database.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(
            namespace='Alexa.ColorController',
            name='color',
            value=request['directive']['payload']['color'])
        return send_response(apcr.get())
def lambda_handler(request, context):
    # Dump the request for logging - check the CloudWatch logs
    print('lambda_handler request  -----')
    print(json.dumps(request))

    if context is not None:
        print('lambda_handler context  -----')
        print(context)

    # Validate we have an Alexa directive
    if 'directive' not in request:
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type':
                'INVALID_DIRECTIVE',
                'message':
                'Missing key: directive, Is the request a valid Alexa Directive?'
            })
        return send_response(aer.get())

    # Check the payload version
    payload_version = request['directive']['header']['payloadVersion']
    if payload_version != '3':
        aer = AlexaResponse(
            name='ErrorResponse',
            payload={
                'type': 'INTERNAL_ERROR',
                'message': 'This skill only supports Smart Home API version 3'
            })
        return send_response(aer.get())

    # Crack open the request and see what is being requested
    name = request['directive']['header']['name']
    namespace = request['directive']['header']['namespace']

    # Handle the incoming request from Alexa based on the namespace

    if namespace == 'Alexa.Authorization':
        if name == 'AcceptGrant':
            # Note: This sample accepts any grant request
            # In your implementation you would use the code and token to get and store access tokens
            grant_code = request['directive']['payload']['grant']['code']
            grantee_token = request['directive']['payload']['grantee']['token']
            aar = AlexaResponse(namespace='Alexa.Authorization',
                                name='AcceptGrant.Response')
            return send_response(aar.get())

    if namespace == 'Alexa.Discovery':
        if name == 'Discover':
            adr = AlexaResponse(namespace='Alexa.Discovery',
                                name='Discover.Response')

            capability_alexa = adr.create_payload_endpoint_capability()

            capability_alexa_power_controller = adr.create_payload_endpoint_capability(
                interface='Alexa.PowerController',
                supported=[{
                    'name': 'powerState'
                }])
            capability_alexa_stepSpeaker_controller = adr.create_payload_endpoint_capability(
                interface='Alexa.StepSpeaker')
            capability_alexa_playback_controller = adr.create_payload_endpoint_capability(
                interface='Alexa.PlaybackController',
                supportedOperations=['Play', 'Pause', 'Stop'])

            adr.add_payload_endpoint(
                friendly_name='TV',
                endpoint_id='ps3-tv',
                manufacturer_name='Sony',
                description='PlayStation 3 TV connected with Raspberry Pi',
                displayCategories=['TV'],
                capabilities=[
                    capability_alexa, capability_alexa_power_controller,
                    capability_alexa_stepSpeaker_controller,
                    capability_alexa_playback_controller
                ])

            return send_response(adr.get())

    if namespace == 'Alexa.PowerController':
        # Note: This sample always returns a success response for either a request to TurnOff or TurnOn
        endpoint_id = request['directive']['endpoint']['endpointId']
        power_state_value = 'OFF' if name == 'TurnOff' else 'ON'
        correlation_token = request['directive']['header']['correlationToken']

        try:
            response = requests.post('{}toggle-power'.format(constants.url),
                                     json={'powerState': power_state_value})

            if response.status_code == 200:
                speech = response.text
            else:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={
                        'type': 'INTERNAL_ERROR',
                        'message': 'There was an error with the endpoint.'
                    }).get()
        except:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PowerController',
                                  name='powerState',
                                  value=power_state_value)
    elif namespace == 'Alexa.StepSpeaker':
        endpoint_id = request['directive']['endpoint']['endpointId']
        correlation_token = request['directive']['header']['correlationToken']

        try:
            if name == 'AdjustVolume':
                response = requests.post(
                    '{}adjust-volume'.format(constants.url),
                    json={
                        'volumeSteps':
                        request['directive']['payload']['volumeSteps']
                    })
            else:
                response = None

            if response and response.status_code == 200:
                speech = response.text
            else:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={
                        'type': 'INTERNAL_ERROR',
                        'message': 'There was an error with the endpoint.'
                    }).get()
        except:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(
            namespace='Alexa.StepSpeaker',
            name='volumeSteps',
            value=request['directive']['payload']['volumeSteps'])
    elif namespace == 'Alexa.PlaybackController':
        endpoint_id = request['directive']['endpoint']['endpointId']
        correlation_token = request['directive']['header']['correlationToken']

        try:
            if name == 'Play' or name == 'Pause' or name == 'Stop':
                response = requests.post(
                    '{}play-pause-stop-chromecast-youtube'.format(
                        constants.url),
                    json={'action': name})
            else:
                response = None

            if response and response.status_code == 200:
                speech = response.text
            else:
                return AlexaResponse(
                    name='ErrorResponse',
                    payload={
                        'type': 'INTERNAL_ERROR',
                        'message': 'There was an error with the endpoint.'
                    }).get()
        except:
            return AlexaResponse(name='ErrorResponse',
                                 payload={
                                     'type': 'ENDPOINT_UNREACHABLE',
                                     'message': 'Unable to reach endpoint.'
                                 }).get()

        apcr = AlexaResponse(correlation_token=correlation_token)
        apcr.add_context_property(namespace='Alexa.PlaybackController',
                                  name='action',
                                  value=name)

    return send_response(apcr.get())