I recently built an Indoor Environmental Sensor Pack that collects office conditions and logs them to DynamoDB through AWS IoT core. For more on that, check out this post.
One of the elements of that project was querying the data in DynamoDB to display it on our office dashboard and our site. To do this I wrote a NodeJS lambda function that queries DynamoDB and returns a JSON payload.
I used Apex Up to deploy the lambda function. Up makes deploying and managing apps on AWS lambda much easier.
I put together the steps I took to do this. I hope it helps!
Install Apex Up and set up your AWS account. Follow the Up docs.
Next, create a new directory and add a app.js
.
mkdir hello
cd hello
app.js:
const http = require('http')
const { PORT = 3000 } = process.env
http.createServer((req, res) => {
res.end('Hello World\n')
}).listen(PORT)
Next deploy it with:
up
Test your function!
$ curl `up url`
Hello World
Next lets query DynamoDB and return the results.
// Use NodeJS's built in http server
var http = require('http');
// Up specifies the port at runtime
const {PORT = 3000} = process.env;
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'us-east-1'});
// Create DynamoDB service object
var dynamo = new AWS.DynamoDB({apiVersion: '2012-08-10'});
http
.createServer(function(req, res) {
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.setHeader('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// Set up query parameters
var params = {
TableName: 'MyTableName',
Limit: 10,
// Set ScanIndexForward to false to display most recent entries first
ScanIndexForward: false,
KeyConditionExpression: 'MyPartitionKey = :MyPartitionKey',
ExpressionAttributeValues: {
':MyPartitionKey': {
S: 'MyPartitionValue',
},
},
};
dynamo.query(params, function(err, data) {
if (err) {
//write a response to the client
console.log(err);
res.write('Internal Server Error');
res.end();
} else {
// Format results for JSON payload
let response = data.Items.map(item => ({
timestamp: item.timestamp.S,
payload: {
temp: item.payload.M.temp.N,
},
}));
// Return results
res.write(JSON.stringify(response));
res.end();
}
});
})
.listen(PORT);
Be sure to replace "MyTable", "MyPartitionKey" and "MyPartitionValue", etc with your actual DynamoDB values!
Next we need to grant the lambda access to the DynamoDB table. Up provides configuration section in up.json
for defining policies:
{
... other settings
"lambda": {
"role": "arn:aws:iam::[SOME NUMBERS]:role/[MY PROJECT]_lambda_function",
"policy": [
{
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:us-east-1:[SOME NUMBERS]:table/[MY Table]",
"Action": [
"dynamodb:Query"
]
}
]
}
}
Deploy again to apply the policy.
At this point, you can run
$ curl `up url` | jq "."
(if you don't have jq
installed, install it with brew install jq
. It is a JSON formatter for the commandline).
And get your DynamoDB JSON payload.
For example:
You can also visit your up url
in the browser to see your data.
You can debug the function with
up logs
Happy hacking!
Dan is an engineer with a background in software development. He graduated from GVSU with BSEE in 2011 and has been building ever since. His tools of choice are C, JavaScript, Elixir and everything that AWS offers.
DEB Associates helps companies through the entire electronics design process. Our team is smart, reliable, and deeply knowledgeable about the intricacies of circuit design, PCB layout, and EMC.