AWS IoT thing connectivity status not reliable - amazon-web-services

I need to get IoT devices status reliable.
Now, I have Lambda connected to SELECT * FROM '$aws/events/presence/#' events on IoT.
But I can't get reliable device status in the case when a connected device was disconnected and connected back within ~ 40 seconds. The result of this scenario - events in the order:
1. Connected - shortly after device was connected again
2. Disconnected - after ~ 40 seconds.
It looks like the message disconnected is not discarded when device is connected back and emitted after connection timeout in any case.
I've found a workaround - request device connectivity from AWS_Things IoT index. In fact, I also receive previous connectivity state, but it has timestamp field. Then, I just compare the current event.timestamp with the timestamp from index and if it higher that 30 seconds - I discard disconnected event silently. But this approach is not reliable, because I am still able get wrong behavior when switching device faster - with 5 seconds interval. This is not acceptable for my project.
Is it possible to use IoT events to solve my problem? I wouldn't like to go in devices index polling..

You can also use an sqs delay queue and check after 5 secs if the disconnect is true. That is way cheaper than using step functions. This is also the official solution.
Handling client disconnections
The best practice is to always have a wait state implemented for lifecycle events, including Last Will and Testament (LWT) messages. When a disconnect message is received, your code should wait a period of time and verify a device is still offline before taking action. One way to do this is by using SQS Delay Queues. When a client receives a LWT or a lifecycle event, you can enqueue a message (for example, for 5 seconds). When that message becomes available and is processed (by Lambda or another service), you can first check if the device is still offline before taking further action.
https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html#connect-disconnect

Well, on this moment I just use StepFunction, connected to SELECT * FROM '$aws/events/presence/#' event that makes check of actual thing state after 10s delay:
{
"StartAt": "ChoiceEvent",
"States": {
"ChoiceEvent": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.eventType",
"StringEquals": "disconnected",
"Next": "WaitDelay"
}
],
"Default": "CheckStatus"
},
"WaitDelay": {
"Type": "Wait",
"Seconds": 30,
"Next": "CheckStatus"
},
"CheckStatus": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:xxxxxxx:function:connectivity-check",
"End": true
}
}
}
The connectivity-check lambda just checks actual thing state in IoT registry when eventType is disconnected

Related

AWS Greengrass V2 Modbus RTU adapter connectivity issue

I have deployed the Greengrass Modbus component to my Raspberry pi 4B with the required dependencies successfully. The pi is connected to a Modbus temperature and humidit sensor via an RS485 USB dongle. I confirm that I can read the holding registers successfully using Modpoll Commandline master simulator tool, all lovely so far. The sensor can be accessed through the path "/dev/ttyUSB0".
I want Greengrass to report the values of these registers on the sensor to AWS IoTCore.
To request data, I send a payload to a specific topic from the AWS broker to the Greengrass core. In my particular case, the topic is the default one "modbus/adapter/request". I sent the following payload:
{
"request": {
"operation": "ReadHoldingRegistersRequest",
"device": 4,
"address": 1,
"count": 2
},
"id": "TestRequest"
}
And I get the following response on the topic "modbus/adapter/response":
{
"response": {
"status": "fail",
"error_message": "Modbus Error: [Connection] Failed to connect[rtu baud[9600]]",
"error": "Exception",
"payload": {
"error": "Modbus Error: [Connection] Failed to connect[rtu baud[9600]]"
},
"operation": "ReadHoldingRegistersRequest",
"device": 4
},
"id": "TestRequest"
}
To reiterate, I know the correct port because I can read the holding registers using commandline Modbuspoll. However, using the tool I can specify more parameters, such as parity type, baud rate, etc... which seems like I can't do here. For your reference, the parameters I used on Modpoll are the following:
Address: 4
Baud rate: 9600
Parity: none
Registers: 1 (or 40001 for PLC)
Path: /dev/ttyUSB0
For your information, all of the steps mentioned above are following this guide: https://docs.aws.amazon.com/greengrass/v2/developerguide/modbus-rtu-protocol-adapter-component.html#modbus-rtu-protocol-adapter-component-input-data
Any suggestion?
Upon looking at the log /greengrass/v2/logs/aws.greengrass.Modbus.log , I quickly realized that it was a permission issue with the pi. I was able to quickly fix it using the sudo chmod 777 command to the port.

Difference between AWS IoT shadow file desired and reported fields

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 ;)

How to send the notification on every task execution in a state machine on AW step functions?

I am working on Amazon Step functions to leverage the workflow for multiple Batch jobs. The requirement is such that the Batch jobs should be executed sequentially and whenever a job transition from one to another job then send a notification with the execution status of the tasks to a SNS topic. I need to send a notification for SUCCESS and FAILURE of a task.
I have tried the Execution Events using Cloudwatch event rules, but Execution Events only gives information about the State Machine's execution, not about the Tasks execution.
As you have found states aren't in Cloudwatch events need to add this as a separate step, there is no way around this, have a notify step which either executes a lambda, or sync to SNS.
There is also another way to do this as you can compose step functions of step functions. So you have your parent step function and your child step function. Your child step function could be the batch job itself, and then you can make use of Cloudwatch events on the batch-job-step-function step function:
"BatchJob" : {
"Comment": "This snippet is in the parent step function. It will kick off another step function, called: batch-job-step-function",
"Type": "Task",
"Resource": "arn:aws:states:::states:startExecution.sync",
"Parameters": {
"StateMachineArn": "arn:aws:states:us-east-1:TODO:stateMachine:batch-job-step-function",
"Input": {
"batchJobInput.$": "$$.Execution.Input.batchJobInput"
}
},
"End": true | "Next" : "TODO"
}
Now you can put Cloudwatch Event Rules against: arn:aws:states:us-east-1:TODO:stateMachine:batch-job-step-function

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.

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?