question

Manusinh_Thakor avatar image
Manusinh_Thakor asked

how can i implement ReportState and ChangeState in smart home skill.

Hello...


I'm new to Alexa skill development. Recently, I'd created a smart home skill from the "create Alexa smart home skill" guide. the skill is created and in the test phase device is discovered by the Alexa app. but when I turn the device on or off, after few seconds the app says the device is unresponsive. when I asked about that issue in the forum, they said that you have to implement ReportState in your skill. So I want to add ReportState and ChangeState in my smart home skill which is written in python. I can't find any example which is in python for the same.


Thanks in advance.

pythonsmart-homealexa-skills-kitproactive-endpoint-management
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

KirkC@Amazon avatar image
KirkC@Amazon answered

Hello. To take a step back, StateReport events and ChangeReport events are two separate but related types of responses you can send. Let's begin then by defining each.

StateReport Event


When you open the Alexa app, go to the "Devices" tab and tap on a specific device, Amazon will send you a ReportState directive every three seconds. You respond to each ReportState directive synchronously by returning a StateReport event.
https://developer.amazon.com/en-US/docs/alexa/smarthome/state-reporting-for-a-smart-home-skill.html#report-state-when-alexa-requests-it


If you do not respond to a ReportState directive with a StateReport event, then you will see the "Device is Unresponsive" message in the Alexa app.


ChangeReport Event


For ChangeReport events, you're not responding to a request sent by Amazon. Instead, you're proactively reporting a change in a device's state to Amazon as a result of some interaction which occurred outside of the Alexa app. These ChangeReport events are sent by making an API call to the Alexa Event Gateway.
https://developer.amazon.com/en-US/docs/alexa/smarthome/send-events-to-the-alexa-event-gateway.html


For example, if I physically turn off a switch, I might want to send a ChangeReport event to the Alexa Event Gateway so that Alexa is aware of the device's change in state. Implementing this change reporting will also allow you to create routines in the Alexa app based upon these changes in state.

As a note, ChangeReport events are optional and can only be sent for device interfaces where "proactivelyReported" was declared as true in the Discover.Response JSON.


Python - Responding With StateReport


Now, to your question of how to create JSON responses using Python. A JSON object is basically just a set of key-value pairs. Within Python, you would create a similar object by making a dictionary.

Because Python dictionaries and JSON aren't 100% the same, you'll want to use the Python "json" module to convert your dictionary to JSON before returning it.

More information on the Python JSON encoder and decoder can be found here:
https://docs.python.org/3/library/json.html


Code Snippet


Here's a sample from my own code used which is used to build a StateReport response to a ReportState directive for a lock device.


import json

...

def build_LockStateReport(correlationToken, BearerToken):
    LockStateReport = {
        "context": {
            "properties": [
                {
                    "namespace": "Alexa.LockController",
                    "name": "lockState",
                    "value": "LOCKED",
                    "timeOfSample": get_utc_timestamp(),
                    "uncertaintyInMilliseconds": 0
                }
            ]
        },
        "event": {
            "header": {
                "messageId": get_uuid(),
                "correlationToken": correlationToken,
                "namespace": "Alexa",
                "name": "StateReport",
                "payloadVersion": "3"
            },
            "endpoint": {
                "scope": {
                    "type": "BearerToken",
                    "token": BearerToken
                },
                "endpointId": "lock-appliance-001",
                "cookie": {}
            },
            "payload": {}
        }
    }
    print("StateReport Response: ", json.dumps(LockStateReport))
    return json.loads(json.dumps(LockStateReport))



Python - Sending A ChangeReport


As with your response to a StateReport, you'll want to convert the Python dictionary that you define to JSON before returning it.

However, since this is a proactive report, you're not synchronously responding to an event sent to your Skill's Lambda function. You therefore must make an API call in your Python code.

The module I like to use for this purpose is "requests". You can learn more about "requests" in the following documentation:
https://docs.python-requests.org/en/master/


The specific headers and body Alexa will expect for a ChangeReport is defined here:
https://developer.amazon.com/en-US/docs/alexa/smarthome/send-events-to-the-alexa-event-gateway.html#message-contents

https://developer.amazon.com/en-US/docs/alexa/smarthome/state-reporting-for-a-smart-home-skill.html#changereport-event


Code Snippet


Similarly, here's a code snipped that I was able to use to proactively report to the Alexa Event Gateway that my "lock-appliance-01" device changed its "lockState" to "UNLOCKED" as a result of a physical interaction:


import requests
import json

url = "https://api.amazonalexa.com/v3/events"

payload = json.dumps({
  "event": {
    "header": {
      "namespace": "Alexa",
      "name": "ChangeReport",
      "messageId": get_uuid(),
      "payloadVersion": "3"
    },
    "endpoint": {
      "scope": {
        "type": "BearerToken",
        "token": "Atza|token-redacted"
      },
      "endpointId": "lock-appliance-001"
    },
    "payload": {
      "change": {
        "cause": {
          "type": "PHYSICAL_INTERACTION"
        },
        "properties": [
          {
            "namespace": "Alexa.LockController",
            "name": "lockState",
            "value": "UNLOCKED",
            "timeOfSample": get_utc_timestamp(),
            "uncertaintyInMilliseconds": 1000
          }
        ]
      }
    }
  },
  "context": {}
})
headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer Atza|token-redacted',
  'Host': 'api.amazonalexa.com'
}

response = requests.request("POST", url, headers=headers, data=payload)

print("Status Code:" + str(response.status_code))
print("Response:" + response.text)


I realize this is a long response but, it's a big question and I hope this information helps get you started!

2 comments
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

@KirkC@Amazon

Hello Support,

Thanks for the detailed answer.

The issue of the device is unresponsive isn't solved yet. I'm new to python and skill development, so I can't understand some code. And in my code ReportState and StateReport is already defined, and I also true the value of proactive state and retrievable, but it's not working. And is there any other settings or configurations I need to check?


Sorry, but I can't implement above code samples in my code. Because I don't know where to put that code sample in my code. I know that's silly, but I'm new to this.

I attached my lambda_function code. Can you please help me?


Thanks in advance.

0 Likes 0 ·
lambda-function.txt (11.9 KiB)

Hi Manusinh_Thakor. Generally speaking we cannot provide specific debugging guidance. From here then my best suggestion would be to implement logging in your skill's Lambda function so that you're logging each request sent to your skill, and each response returned by your skill.


Once that logging has been implemented, you can open the Alexa app, tap the "Devices" tab, and choose the device in question. With the device details page open your back-end will receive a ReportState directive every three seconds.


Once you've logged your response JSON, you may refer to our tech docs to see whether your StateReport response is formatted correctly. You can find specific examples for each interface as well be clicking the "Smart Home Skill APIs" dropdown menu on the left and clicking the name of the interface in question:
https://developer.amazon.com/en-US/docs/alexa/smarthome/state-reporting-for-a-smart-home-skill.html#statereport-event


As a note, one common pitfall that I've seen is that developers will have a discrepancy between the supported capability interfaces as described in the skill's Discover.Response JSON, and the capabilities reported in the "properties" array of the skill's StateReport response. If there's a mismatch, that too can cause the "Device is unresponsive" messaging.


So, if you find that the skill is returning a valid JSON StateReport response, you may want to go back and look at which capability interfaces you declared support for in the Discover.Response JSON for the device in question to see whether you're omitting anything declared in the Discover.Response JSON, or including something not declared in the Discover.Response JSON.

0 Likes 0 ·