예제 #1
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')
예제 #3
0
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())
예제 #4
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
예제 #5
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']

    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())
예제 #6
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 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())
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 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())
예제 #10
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())
예제 #11
0
    def process(self, request, client_id, client_secret):
        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='APISensorEndpointDetails',
                        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)

                    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:
                        statereport_response.add_context_property(
                            namespace=p['interface'],
                            name=p['properties']['supported'][0]['name'],
                            value=DEFAULT_VAL[p['interface']])

                    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)
                response_token = api_auth.get_access_token(
                    grant_code, client_id, client_secret)
                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('APISensorUsers')
                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"),
                        '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.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 associated with the user
                table = boto3.resource('dynamodb').Table(
                    'APISensorEndpointDetails')
                result = table.scan(FilterExpression=boto3.dynamodb.conditions.
                                    Attr('UserId').eq(user_id))

                for endpoint_details in result['Items']:

                    # We have an endpoint
                    print(
                        'LOG api_handler_directive.process.discovery: Found:',
                        endpoint_details['EndpointId'], 'for user:'******'FriendlyName'],
                        endpoint_id=endpoint_details['EndpointId'],
                        capabilities=json.loads(
                            endpoint_details['Capabilities']),
                        display_categories=json.loads(
                            endpoint_details['DisplayCategories']),
                        manufacturer_name=endpoint_details['ManufacturerName'])

                response = adr.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