Difference between AWS IoT shadow file desired and reported fields - amazon-web-services

I'm looking at the AWS IoT documentation for shadow states and trying to better understand the use of desired and reported in the shadow file.
The documentation states:
When the shadow's state changes, AWS IoT sends /delta messages to all MQTT subscribers with the difference between the desired and the reported states.
After looking through the rest of the documentation I don't feel like I have a clear grasp of the use case for desired vs reported. Can someone explain the use case? When do we use one vs. the other?

Let's start from the beginning, a device shadow is a persistent virtual shadow of a Thing defined in AWS IoT Registry. Basically, it’s a JSON State Document that is used to store and retrieve current state information for a Thing. You can interact with a Device Shadow using MQTT Topics or REST API calls. The main advantage of Shadows is that you can interact with it, regardless of whether the thing is connected to the Internet or not.
A shadow’s document contains a state property that describes aspects of the device’s state:
{
"state": {
"desired": {
"color": "RED"
},
"reported": {
"color": "GREEN"
},
"delta": {
"color": "RED"
}
}
}
Here's a description of each state:
Apps specify the desired states of device properties by updating the desired object.
Devices report their current state in the reported object.
AWS IoT reports differences between the desired and the reported state in the delta object.
Every shadow has a reserved MQTT Topic and HTTP URL that supports the get, update, and delete actions on the shadow. Let's take a look:
$aws/things/THING_NAME/shadow/update: publish to this Topic to update/create the Thing Shadow;
$aws/things/THING_NAME/shadow/update/accepted: AWS IoT publishes reported or desired portion of the State Document to this Topic, on accepting the update request;
$aws/things/THING_NAME/shadow/update/rejected: AWS IoT publishes an Error Message to this Topic when it rejects update request;
$aws/things/THING_NAME/shadow/update/documents: AWS IoT publishes a State Document with Previous and Current State information to this topic whenever an update to the shadow is successfully performed;
$aws/things/THING_NAME/shadow/update/delta: AWS IoT publishes a response Delta State Document to this topic when it accepts a change for the thing shadow and the request state document contains different values for desired and reported states.
Here's an example. Let's say that we have an air purifier and we want to change the fan speed. The flow will be the following:
User changes the fan speed from the air purifier mobile application
The mobile application publishes the following JSON message to this MQTT topic: $aws/things/THING_NAME/shadow/update to update the device shadow with a new desired state: "fanSpeed": 50. It will look like this:
{
"state": {
"desired": {
"fanSpeed": 50
}
}
}
On successful shadow update, if the previous reported state is different from "fanSpeed": 50, AWS IoT will publish desired state to delta topic $aws/things/THING_NAME/shadow/update/delta.
The shadow state document may look like this:
{
"state": {
"desired": {
"fanSpeed": 50
},
"reported": {
"fanSpeed": 100
},
"delta": {
"fanSpeed": 50
}
}
}
The device (our air purifier) that is subscribed to delta topic will perform the requested operation (set fan speed to 50 in this case), and report back the new state to AWS IoT Device Shadow, using Update Topic $aws/things/THING_NAME/shadow/update with following JSON message:
{
"state": {
"reported": {
"fanSpeed": 50
}
}
}
Now our air purifier has a fan speed of 50... and that's how it works ;)

Related

AWS IoT Shadow - How to handle or reject invalid "desired" states?

AWS IoT Shadow has support for dealing with invalid states. From my understanding of the AWS documentation, when a message is published to /update and it is considered invalid (e.g. because it is invalid json), an error message is published to /update/rejected per specification here https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-error-messages.html
This is clear, but it only concerns generic state update failures.
Question:
What if an AWS IoT shadow state update is valid from the point of view of the AWS IoT Shadow service, but it is not a valid desired state from the point of view of the device?
For example, say a device supports "state": {"desired": {"color": "red"}} and "state": {"desired": {"color": "green"}}.
What is then a good way or best-practice to deal with a request for "state": {"desired": {"color": "black"}} if the device does not support black?
Can this be communicated over any of the default shadow topics?
Note: I found a similar (unanswered) question here: https://forums.aws.amazon.com/thread.jspa?threadID=300362
I recently had a similar problem and found this post on the AWS forum:
https://repost.aws/questions/QUx_YtxvdmTFODhuuNd4D_Yw/how-to-deal-with-shadow-updates-initated-by-device-not-and-server
Basically, the client can clear the "desired" section of the device shadow document to show that it has rejected the changes. This will prevent any more "delta" messages for that particular change. You can clear the device shadow "desired" section by posting a message to /update with null, as follows:
Clear entire desired section:
{
"state" : {
"desired" : null
}
}
Clear an individual field:
{
"state" : {
"desired" : {
"MyField" : null
}
}
}
However, this will not inform the other end (cloud, mobile app, etc) that the "desired" state they requested was invalid.
To do that, you might be able to post your own message to /update/rejected, although I haven't tried this.

How can I use TTL to prevent a message backlog when using Firebase Cloud Messaging with Django-Push-Notifications?

I am working with Firebase Cloud Messaging in Django using django-push-notifications to deliver push notifications to our users via desktop notifications.
After a browser is fully closed (such as when the the computer is turned off), our users receive a backlog of all notifications previously sent next time they boot up.
While there are situations where a user would want to receive the entire backlog of messages, this is not one of them.
It seems the answer is to set TTL=0, as per this section of the FCM documentation, but my attempts are not resulting in the desired behavior.
Please help me better understand TTL in this context. If TTL is the right way to go, what is the proper way to format TTL in send_message() using django-push-notifications so that messages will not accumulate if not immediately delivered?
Here is what I have attempted:
devices.send_message(
body,
TTL=0,
time_to_live=0,
link='blah',
extra={'title': 'blah blah', 'icon': '/foo/bar.png'}
)
The format that you send seems different from the one in the documentation you linked. From the documentation:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
"apns":{
"headers":{
"apns-expiration":"1604750400"
}
},
"android":{
"ttl":"4500s"
},
"webpush":{
"headers":{
"TTL":"4500"
}
}
}
}
So key here is that the time-to-live for a webpush message is set under webpush/headers/TTL, while you're adding it to the top-level.

GCP stackdriver fo OnPrem

Based on Stackdriver, I want to send notifications to my Centreon monitoring (behind Nagios) for workflow reasons, do you have any idea on how to do so?
Thank you
Stackdriver alerting allows webhook notifications, so you can run a server to forward the notifications anywhere you need to (including Centreon), and point the Stackdriver alerting notification channel to that server.
There are two ways to send external information in the Centreon queue without a traditional passive agent mode.
First, you can use the Centreon DSM (Dynamic Services Management) addon.
It is interesting because you don't have to register a dedicated and already known service in your configuration to match the notification.
With Centreon DSM, Centreon can receive events such as SNMP traps resulting from the detection of a problem and assign the event dynamically to a slot defined in Centreon, like a tray event.
A resource has a set number of “slots” on which alerts will be assigned (stored). While this event has not been taken into account by human action, it will remain visible in the Centreon web frontend. When the event is acknowledged, the slot becomes available for new events.
The event must be transmitted to the server via an SNMP Trap.
All the configuration is made through Centreon web interface after the module installation.
Complete explanations, screenshots, and tips are described on the online documentation: https://documentation.centreon.com/docs/centreon-dsm/en/latest/user.html
Secondly, Centreon developers added a Centreon REST API you can use to submit information to the monitoring engine.
This feature is easier to use than the SNMP Trap way.
In that case, you have to create both host/service objects before any API utilization.
To send status, please use the following URL using POST method:
api.domain.tld/centreon/api/index.php?action=submit&object=centreon_submit_results
Header
key value
Content-Type application/json
centreon-auth-token the value of authToken you got on the authentication response
Example of service body submit: The body is a JSON with the parameters provided above formatted as below:
{
"results": [
{
"updatetime": "1528884076",
"host": "Centreon-Central"
"service": "Memory",
"status": "2"
"output": "The service is in CRITICAL state"
"perfdata": "perf=20"
},
{
"updatetime": "1528884076",
"host": "Centreon-Central"
"service": "fake-service",
"status": "1"
"output": "The service is in WARNING state"
"perfdata": "perf=10"
}
]
}
Example of body response: :: The response body is a JSON with the HTTP return code, and a message for each submit:
{
"results": [
{
"code": 202,
"message": "The status send to the engine"
},
{
"code": 404,
"message": "The service is not present."
}
]
}
More information is available in the online documentation: https://documentation.centreon.com/docs/centreon/en/19.04/api/api_rest/index.html
Centreon REST API also allows to get real-time status for hosts, services and do the object configuration.

AWS SNS: how to send custom data within a push notification

We have a case where we need to send a json object with a push notification. Reading the documentation I found out I can do the following
iOS
{
default: req.body.message,
"APNS": {
"aps": {
"alert": {
"message": req.body.message,
"data": "{JSON Object}"
},
},
}
Android:
{
"GCM": {
"data": {
"messagee": {
"message": req.body.message,
"data": "{JSON Object}"
}
}
}
}
But, I got sceptical if we should use Message Attributes if not then what is the us of the Message Attributes !
Based on your description it seems like you do not need to use message attributes. Quoting the AWS docs:
You can also use message attributes to help structure the push notification message for mobile endpoints. In this scenario the message attributes are only used to help structure the push notification message and are not delivered to the endpoint, as they are when sending messages with message attributes to Amazon SQS endpoints.
There are some use cases for attaching message attributes to push notifications. One such use case is for TTLs on outbound messages. Again quoting the docs:
The TTL message attribute is used to specify expiration metadata about a message. This allows you to specify the amount of time that the push notification service, such as Apple Push Notification Service (APNS) or GCM, has to deliver the message to the endpoint. If for some reason (such as the mobile device has been turned off) the message is not deliverable within the specified TTL, then the message will be dropped and no further attempts to deliver it will be made. To specify TTL within message attributes, you can use the AWS Management Console, AWS software development kits (SDKs), or query API.

AWS IoT to to send once-off real-time command to device

I have a weather station which is publishing to AWS IoT.
It reports it's state as well as measurements of the environment by publishing to shadows service messages of the format:
{
"state": {
"reported": {
"temperature" : 22,
"humidity" : 70,
....
"wind" : 234,
"air" : 345
}
}
The station has some interactive properties like _led1 and _led2 which I can also report and update via Shadows service by setting "desired" state. To do that I can send to a device message like that:
{
"state": {
"desired": {
"_led1" : "on",
"_led2" : "off",
....
"_lock99" : "open"
}
}
Thanks to shadow service Whenever device gets online it will receive synchronized state and will turn the leds and locks into desired position.
However, sometimes I want to operate the device in real-time: when troubleshooting a device - I want to send a real-time command to reboot it - and if device is live and receives the message I want to reboot it. If device was offline, then nothing happens (the reboot command never reaches the device).
So what would be the best way to control device in real-time? Still try to play with the shadows service to achieve that? Or simply create a separate topic eg. my-things/{thing_name}/real-time-commands and force device to subscribe to it?