How to publish to AWS Shadow from lambda - amazon-web-services

This is the code Iam using,
var AWS = require('aws-sdk');
var iotdata = new AWS.IotData({
endpoint: '###########.iot.ap-south-1.amazonaws.com'
});
exports.handler = async (event) => {
var params = {
payload: Buffer.from('...') || 'STRING_VALUE'
encoded on your behalf */, /* required */
thingName: 'ESP32', /* required */
//shadowName: 'STRING_VALUE'
};
iotdata.updateThingShadow(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
};
I referred to this from the given link,
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/IotData.html#updateThingShadow-property
But I cant update my shadow.
I also dont understand in which format I should include the payload.
I am running this on AWS Lambda function in Nodejs 12.x environment. I also dont receive any errors in cloudwatch . Cloudwatch tells me execution result has succeeded? Can you help me?
I have already given permission for Lambda to updateShadow.

This the final correct code .....
var AWS = require('aws-sdk');
var iotdata = new AWS.IotData({
endpoint: '#######.iot.ap-south-1.amazonaws.com'
});
exports.handler = async (event) => {
var POST_DATA = JSON.stringify({"state":{"desired":{"state":10}}});
await new Promise((resolve, reject) => {
var params = {
payload:POST_DATA ,
thingName: 'ESP32', /* required */
//shadowName: 'STRING_VALUE'
};
iotdata.updateThingShadow(params, function(err, data) {
if (err) {
console.log(err, err.stack);
console.log("error................")// an error occurred
reject(err);
} else {
console.log(data); // successful response
resolve(data)
}
});
})
}

The issue here is that you are using the async Lambda handler. So while your updateThingShadow() call is in progress, the Lambda function completes and exits. You need to wait for that call to complete. There are two ways to do that -
Approach 1: (A simpler async-await syntax)
var AWS = require('aws-sdk');
var iotdata = new AWS.IotData({
endpoint: '###########.iot.ap-south-1.amazonaws.com'
});
exports.handler = async (event) => {
var params = {
// Define params
};
try {
const data = await iotdata.updateThingShadow(params).promise();
console.log(data);
} catch (err) {
console.log(err);
}
};
Approach 2: (If you prefer using the callback approach)
var AWS = require('aws-sdk');
var iotdata = new AWS.IotData({
endpoint: '###########.iot.ap-south-1.amazonaws.com'
});
exports.handler = async (event) => {
var params = {
// Define params
};
await new Promise((resolve, reject) => {
iotdata.updateThingShadow(params, function(err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
reject(err); // End the promise with an error
} else {
console.log(data); // successful response
resolve(data); // End the promise with success
}
});
})
};

Related

Lambda not triggering codebuild to run?

I am trying to have lambda trigger a codebuild function when it hits the point within the lambda function, here is the current code im using for lamda:
console.log('Loading function');
const aws = require('aws-sdk');
const s3 = new aws.S3();
exports.handler = async (event, context) => {
const codebuild = new aws.CodeBuild();
let body = JSON.parse(event.body);
let key = body.model;
var getParams = {
Bucket: 'bucketname', // your bucket name,
Key: key + '/config/training_parameters.json' // path to the object you're looking for
}
if (key) {
const objects = await s3.listObjects({
Bucket: 'bucketname',
Prefix: key + "/data"
}).promise();
console.log(objects)
if (objects.Contents.length == 3) {
console.log("Pushing")
await s3.getObject(getParams, function(err, data) {
if (err)
console.log(err);
if (data) {
let objectData = JSON.parse(data.Body.toString('utf-8'));
const build = {
projectName: "projname",
environmentVariablesOverride: [
{
name: 'MODEL_NAME',
value: objectData.title,
type: 'PLAINTEXT',
},
]
};
console.log(objectData.title)
codebuild.startBuild(build,function(err, data){
if (err) {
console.log(err, err.stack);
}
else {
console.log(data);
}
});
console.log("Done with codebuild")
}
}).promise();
const message = {
'message': 'Execution started successfully!',
}
return {
'statusCode': 200,
'headers': {'Content-Type': 'application/json'},
'body': JSON.stringify(message)
};
}
}
};
Specifically this part should trigger it:
codebuild.startBuild(build,function(err, data){
if (err) {
console.log(err, err.stack);
}
else {
console.log(data);
}
});
But its not, it even outputs after the function? Im thinking its something to do with promises/await/async but cant find the right solution? Any help would be appreciated.
As you pointed out the problem is related to promises. Change your code like this:
const result = await codebuild.startBuild(build).promise();
And if you configured your lambda permissions for CodeBuild it should work.
You can change your s3.getObject the same way without the callback function:
const file = await s3.getObject(getParams).promise();
console.log(file.Body);

How to scan the dynamodb table form the AWS Lambda function

I am trying to scan the Dynamodb table form my following code, can anyone please guide me what is wrong here.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB({
region: "eu-west-1",
apiVersion: "2012-08-10"
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
dynamodb.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
I have given full dynamodb access role to the function but still it gives me the null response. Any idea what can be wrong here?
Response:
I tried with dynaomClient which not working too.
const AWS = require("aws-sdk");
const db = new AWS.DynamoDB.DocumentClient({
region : 'eu-west-1'
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
db.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
Your Lambda function is async but your code uses callbacks. By the time the callback is reached, your function has already been terminated because it ran asynchronously. I'd speculate that the null output you see is the return value from the Lambda function, not your console.log.
Replace your call to scan with the following:
try{
let results = await db.scan(params).promise()
console.log(results);
} catch(err){
console.log(err)
}
For more info, check out the AWS documentation about working with promises.

Lambda SDK Calls No Response

I am trying to do a pretty simple "hello world" in AWS Lambda. I tried a few services that only call the AWS SDK and just try to read. My callback never gets called. I have to be missing something. Any help appreciated!
var AWS = require("aws-sdk");
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
var s3 = new AWS.S3(); // confirmed this is not null
s3.listBuckets({}, function(err, data) {
// never reaches here!
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
return response;
};
I did create a role this lambda is using that has S3 access. :-)
It seems that because I chose the Node 8.x runtime, I needed to use one of those async constructs. This worked...
let AWS = require('aws-sdk');
let s3 = new AWS.S3();
exports.handler = async (event) => {
return await s3.listBuckets().promise() ;
};
This is a synchronization problem.
Your return response code is executed before your callback is invoked.
you'll have to put your return statement inside your callback or use async/await
Returning inside your callback:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
var s3 = new AWS.S3();
s3.listBuckets({}, function (err, data) {
if (err) {
console.log(err, err.stack);
return {
statusCode: 500,
message: 'some error'
}
}
return response
});
}
Using async/await:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200
};
var s3 = new AWS.S3();
await s3.listBuckets().promise();
return response;
}
I'd go with the async/await approach as it's much cleaner and more readable. It's also easier to work with promises than with callbacks.
EDIT: The OP claimed it didn't work. So I have decided to test it on my own. The above code works, with a very small change just to add the listed buckets to the response. Here's the final code:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200
};
var s3 = new AWS.S3();
const buckets = await s3.listBuckets().promise();
response.body = JSON.stringify(buckets);
return response;
}
And here's the output in CloudWatch Logs:

Calling AWSCognito signup from lambda function

I am trying to create a lambda function to create a user whenever there is an update in one of the tables of dynamo db.
I have created a dynamodb table with a trigger. I get "adminCreateUser not a function" error when i run the below code in lambda.
lambda function:
exports.handler = function(event, context) {
// TODO implement
cognitoidentityserviceprovider.adminCreateUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
context.done(null, 'Hello from Lambda');
};
It should be just the code below. Maybe make sure adminCreateUser is in your main AWS SDK, it was only introduced pretty recently.
const AWS = require('aws-sdk');
exports.handler = (event, context, callback) => {
AWS.config.apiVersions = {
cognitoidentityserviceprovider: '2016-04-18'
};
AWS.config.update({accessKeyId: 'akid', secretAccessKey: 'secret'});
var cognito = new AWS.CognitoIdentityServiceProvider({
region: 'us-east-1'
});
params = {};
cognito.adminCreateUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else
console.log(data); // successful response
});
context.done(null, 'Hello from Lambda');
};

Node js: How to set aws cloudwatch alarm state

Tried with below lambda function which will change the state of alarm "OnSNSFailureArm".
exports.handler = (event, context, callback) => {
var params = {
AlarmName: 'OnSNSFailureArm',
StateReason: 'Change Dynamically',
StateValue: "INSUFFICIENT_DATA"
};
cloudwatch.setAlarmState(params, function(err, data) {
if (err){
console.log(err, err.stack);
context.done();
}
else{
console.log(data);
context.done();
}
});
};