Most people have to travel to the grocery store, or other places, with the basic COVID-19 defense: a mask, gloves, and social distancing. However, even with these precautions, many people are getting sick with the disease. This is spreading fear for society. So how do we, as a community, know who is safe, where the most cases are, and how to protect ourselves? That was the motive for this project.
Introduction/DescriptionMy project has three features: a temperature scanner, a reporter to a database using AWS DynamoDB, and a Q&A with Alexa Developer Console (another AWS service). By following an Adafruit tutorial, we were able to use a 1.44 inch TFT with micro SD card reader and Adafruit AMG8833 sensor with Arduino in order to display the sensed reading on TFT (blue is cold, red is hot). We also used an ultrasonic sensor for temperature correction.
CostThe idea for this was to provide a low-cost solution to detecting people with possible COVID and spreading awareness of this.
- Arduino Mega $15
- AMG8833 sensor $40
- Ultasonic sensor $2
- NodeMCU v1.0 $7
- Adafruit 1.44 inch TFT $15
- LCD 16 pin (16x2) $4
- Potentiometer $0.9
- 220 Ω resistor $0.1
- SD card (16 or 32 GB) $5
- Soldering kit (only to solder) $10
- Alexa Echo Dot $20
AWS units
- AWS Free-tier
- AWS DynamoDB: Free-tier, $0.59 per month
- AWS Lambda: Free-tier,
This totals to $119 for the model, and 59 cents per month for AWS. Although this may seem expensive at first, this can scan hundreds of people per day, without breaking. In the long run, this may actually be very low-priced. (Assuming the backup is taken of the SD card when full)
Prep Step : Soldering and install librariesBefore any coding, the AMG8833 and TFT must be soldered. The AMG8833 and TFT came with the pin headers, so we used that and a solder kit to solder the pins. Any solder and solder kit is fine for soldering, the two main essential parts are solder and a solder iron.
Next open up arduino IDE. Once loaded, go to Tools>ManageLibraries. Next, search Adafruit AMG8833. Install the latest version of the library. This will ask you to install other libraries including the one for the TFT. Make sure to accept this.(Click Install all)
Once it is done installing the required libraries, install the LCD library by searching up LiquidCrystal in the library manager. Go ahead and install that. If it asks to install other libraries, please accept that.
Lastly, let's install the HC-SR04 library. Unfortunately, the library is online.
Please note this repository is NOT MY LIBRARY. WE DO NOT OWN IT. It is from Elegoo's The Most Complete Starter Kit Mega 2560 Project CD. We just uploaded online since we could not upload a.zip file into this Hackster.io project.
Step 1: Set up sensor to get temperature pixels.This is page 4 of the Adafruit AMG8833 Thermal Camera Tutorial. (Arduino Wiring & Test)
First, wire the AMG8833. It will look like this. The communication is through I2C.
Next, load up the code in File>Examples> (scroll down to "Examples from Custom Libraries") >AdafruitAMG88xxLibrary>amg88xx_test. This is to test the sensor to make sure it is working before the pixels reading.
CodeSpecifications:
This line is used to read the pixels of the sensor.
amg.readPixels(pixels);
Where 'amg' is an instance of the Adafruit_AMG88xx library, as shown before the 'void setup()'
Adafruit_AMG88xx amg;
After the pixels are read, it uses a FOR loop to print out the data. This is the 8x8 data in which the TFT reads to make the colors. (for later)
Serial.print("[");
for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
Serial.print(pixels[i-1]);
Serial.print(", ");
if( i%8 == 0 ) Serial.println();
}
Serial.println("]");
Serial.println();
After this is loaded, run the program. If you open the serial monitor, the program should report a reading around your room temperature, if nothing is over the sensor. Notice this in Celsius and not in Fahrenheit.
Now, put your hand (your palm area) over the sensor. You should get a reading temperature from 29 degrees to 32 degrees.
Please note, that the hand temperature is lower than the face/body temperature. Please refer to this image from this link for more details.
We are aiming to scan the white/red areas in the hand diagram. This is close to 30-31 degrees, on average. Later, we will show code to determine the real temperature.
Step 2: Use TFT (1.44") to display colorsFrom the pixels, it is easy to translate that into colors for the TFT. This is from page 5 of the Adafruit AMG8833 Thermal Camera Tutorial.
Here is how to wire the TFT (1.44") with the AMG8833 sensor. The TFT uses SPI pins.
Next, load up the code in File>Examples>AdafruitAMG88xxLibrary>thermal_cam
IMPORTANT: This example code is written as Arduino Uno SPI pins. To change it to Mega, locate this line of code (line 27):
#define TFT_CS 10 //chip select pin for the TFT screen
Make sure to change 10 to 53 her since the TCS pin is connected to 53.
#define TFT_CS 53 //chip select pin for the TFT screen
Press CTRL S to save, or Command S on Mac. It will prompt you to save it in another directory, so choose a place to store the program.
Rundownofcode:
This step is an "add-on" to the first step.
Obviously, the code needs to include the SPI library, as well as the TFT and Graphics library, as shown here
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
Next, the TFT will need to define the TCS, RST, and DC pins as well as the min and max temperatures.
#define TFT_CS 10 //chip select pin for the TFT screen
#define TFT_RST 9 // you can also connect this to the Arduino reset
// in which case, set this #define pin to 0!
#define TFT_DC 8
//low range of the sensor (this will be blue on the screen)
#define MINTEMP 22
//high range of the sensor (this will be red on the screen)
#define MAXTEMP 34
After that, we have the color definition (for displaying) and making a TFT object.
const uint16_t camColors[] = {0x480F,
0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,
0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,
0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,
0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,
0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,
0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,
0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,
0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,
0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,
0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,
0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,
0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,
0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,
0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,
0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,
0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,
0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,
0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,
0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,
0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,
0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,
0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,
0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,
0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,
0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,
0xF080,0xF060,0xF040,0xF020,0xF800,};
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
After that, we have definitions for delay time, width/height, and fill screen to start the program
unsigned long delayTime;
uint16_t displayPixelWidth, displayPixelHeight;
tft.initR(INITR_144GREENTAB); // initialize a ST7735S chip, black tab
tft.fillScreen(ST7735_BLACK);
displayPixelWidth = tft.width() / 8;
displayPixelHeight = tft.height() / 8;
Instead of printing the temperatures in the for loop, there is a usage of the "fillRect(start_h start_w. h, w, color)" function and a couple lines of code that maps the colors to display from the pixel[] array from earlier.
for(int i=0; i<AMG88xx_PIXEL_ARRAY_SIZE; i++){
uint8_t colorIndex = map(pixels[i], MINTEMP, MAXTEMP, 0, 255);
colorIndex = constrain(colorIndex, 0, 255);
//draw the pixels!
tft.fillRect(displayPixelHeight * floor(i / 8), displayPixelWidth * (i % 8),
displayPixelHeight, displayPixelWidth, camColors[colorIndex]);
}
Once you run the code, you will see many colors on the TFT, when a warm object is placed. Red means very warm, where as blue means cold. When you put your hand, (assuming you do not have COVID-19) the TFT should show distinction between the room temperature and your temperature (your hand should be yellow or green)
One thing we have noticed is that the temperature gets colder when the hand is farther.
For example, when one of us put their hand over the sensor at 10 cm, it was 0.75 of a degree higher than when they put it at 30 cm. To correct this, we used an ultrasonic sensor to get distance, and add a value to the temperature to make it more accurate.
Howan ultrasonic sensor works
Ultrasonic sensor uses sound waves to determine the time it took to bounce the sound wave off an object and come back to the sensor. Then, it uses the equation d=rt
to determine the distance given rate (speed of sound) and time (time it took to bounce off an object and come back)
Here is a GIF video to show how this concept works.
The hc-sr04 pins need to be turned so it is to the back. This makes it scan vertically like the amg8833.
Now, add the ultrasonic sensor like this:
Add the connections:
Open the arduino file from step 2.
Code Additions/Modifications
Locate #include <Adafruit_AMG88xx.h>
Under that, write this line of code
#include <SR04.h>
This includes the SR04 library
Locate #define MAXTEMP 34
Under that, write these lines of code
#define trig 12
#define echo 11
SR04 sr04 = SR04(echo,trig);
long dist;
This initializes the trig and echo pins as well as make a ultrasonic sensor object with a initialization of distance
Locate this
amg.readPixels(pixels);
Under that, write this
float maxx = -99.9;
This makes a very low max value (this is for later; also please note max is a reserved word so we had to use maxx)
for(int i=0; i<AMG88xx_PIXEL_ARRAY_SIZE; i++){
uint8_t colorIndex = map(pixels[i], MINTEMP, MAXTEMP, 0, 255);
colorIndex = constrain(colorIndex, 0, 255);
//draw the pixels!
tft.fillRect(displayPixelHeight * floor(i / 8), displayPixelWidth * (i % 8),
displayPixelHeight, displayPixelWidth, camColors[colorIndex]);
}
Under that, write these lines of code
dist=sr04.Distance();
Serial.print(dist);
Serial.println(" cm");
This gets the distance of ultrasonic sensor
Locate
tft.fillRect(displayPixelHeight * floor(i / 8), displayPixelWidth * (i % 8), displayPixelHeight, displayPixelWidth, camColors[colorIndex]);
Under that, write these lines of code
if(pixels[i]>maxx){
maxx = pixels[i];
}
This gets the max value out of the 64 pixels.
Locate
dist=sr04.Distance();
Serial.print(dist);
Serial.println(" cm");
Under that, write this
Serial.println(maxx);
Upload
Next, upload the code.
Open the serial monitor. Put your hand about 6-12 cm away from the sensor. This is the target zone, although the sensor may be able to scan farther than that.
Is there...a problem?
Short answer: yes, there is.
Later, we will provide a line of code that makes the hand temperature correct to 37 degrees C. If this line of code thinks the air is a hand, it may say the air temperature is 80 or 90 degrees C
To fix this, you need to add a if loop to determine if an object (like a hand) is close to the sensor. We also need to put the Serial.print(maxx) in the if-else.
Locate these lines of code
Serial.print(dist);
Serial.println(" cm");
Serial.println(maxx);
Replace those lines with these
if(dist>40){
Serial.println("Come closer");
}
else{
if(dist<6){
Serial.println("Go farther");
}
else{
Serial.print(dist);
Serial.println(" cm");
Serial.println(maxx);
}
}
Also, there is another problem. This program does the temperature readings super fast. If we were to save these readings on an SD card (which is done later in the project), it may consume a lot of space. To fix it, use the delay() function to delay the code so it runs at a reasonable pace.
Locate this line of code:
Serial.println(maxx);
}
}
Under that, write this line of code:
delay(200);
This program now will run at 5 hertz, or 5 iterations per second.
Now run it. Open Serial monitor. You should only get real numbers for when a hand is in the correct range. Otherwise, it should say "Come closer" or "Go farther"
Temperature Correction:
Find this line of code
Serial.println(maxx);
Replace it with these lines of code.
float newmax = round((maxx+5.25+(dist/9))*100);
float new2 = newmax/100;
Serial.println(new2);
In that equation, we used various scatter plots with different temperatures to determine a best line of fit. We found that the distance had to be divided by 9, and then added to 4.25. To make sure this is to 2 decimal places, we used round(), *100, and /100.
Basically, we determined every 9 centimeters away the hand is, the temperature drops by one degree using scatter plots.
Now run the code. It should properly display your temperature with the distance.
We live in the United States, where most commonly Fahrenheit scale is used. We used the conversion equation from C to F (F = 1.8*C+32)
To change it to Fahrenheit, locate this line of code
float new2 = newmax/100;
Underneath that, write this line of code
float degreesF = 1.8*new2+32;
Find this line of code
Serial.println(new2);
Replace it with this line of code
Serial.println(degreesF);
If you run it, you should get a reading around 98.6 degrees F.
The LCD works by using Data bus pins to transmit data, LED for back-light as well as many contrast pins.
Here is a GIF video to explain how an LCD works.
The register select, enabler, and DB 4-7 will be connected to Arduino digital pins. Command Voltage will be connected to a 10K Ω potentiometer, which is connected to 5V and Ground. Ground, Read/Write, and LED- will be connected to Arduino Ground. 5V and LED+ (with 220Ω resistor) will be connected to Arduino 5 volts.
Add the LCD connections:
We will use the Liquid Crystal library to communicate with LCD.
CodeModifications/Additions
Find this line of code
#include <SR04.h>
Under that, write this line
#include <LiquidCrystal.h>
Find this line of code
SR04 sr04 = SR04(echo,trig);
Under that, write this line
LiquidCrystal lcd(27, 28, 29, 30, 31, 32);
Find this line of code
Serial.println("-- Thermal Camera Test --");
Under that, write this line
lcd.begin(16, 2);
Find this line of code
Here is how to print the data onto the LCD.
Serial.println(degreesF);
Under that, write these lines.
lcd.setCursor(0, 0);
lcd.print("Temp: "+String(degreesF));
Find this line of code
delay(200);
Under that, write this
lcd.clear();
For too close and too far, let's write the same statements we wrote for Serial on the lcd.
Find this line of code
Serial.println("Come closer");
Under that, write this
lcd.print("Come closer");
Lastly, find this:
Serial.println("Go farther");
Under that, write this
lcd.print("Go farther");
Upload
Now, upload the code.
It should say "Temp:" followed by your temperature on the LCD when you place your hand over the sensor.
(Note: we know it says in the materials to use 2 full length size breadboards. However, we only had 1 full length size breadboard, so we used that and 2 half size breadboards.)
Step 5: Adding a statusSo we have scanned a temperature. Is this person safe? Does he need to go home? Does he need ER care?
We used if loops to determine a "status" of the temperature.
- Below 100.4 degrees F (38 degrees C) --> OK
- 100.4 to 102.2 (39 degrees C) --> send home
- Above 102.2 --> needs ER care
Let's add this to the Code.
Locate this line of code
lcd.print("Temp: "+String(degreesF));
Under that, write these lines of code
if(degreesF < 100.4){
lcd.print("Person is safe");
}
else{
if(degreesF <= 102.2){
lcd.print("Send person home");
}
else{
lcd.print("Person go to ER");
}
}
This should provide a status message below the temperature.
Upload
Upload the code to Arduino. It should say the temperature followed by the status.
In case CDC, or the owner of the building wants to look at the data for analysis or reporting to a website, he or she can take out the micro SD card from the TFT.
This TFT only supports 32 GB or less. In other words, micro SD or micro SDHC only is supported.
We are using a 32 GB micro SD card for best results. This is where the TFT CCS > Arduino 4 as the card pin connection comes into play.
The micro SD card uses SPI.
Addthistothecode
Locate this line of code:
#include <LiquidCrystal.h>
Under that, write this line:
#include <SD.h>
Locate this line of code
LiquidCrystal lcd(27, 28, 29, 30, 31, 32);
Under that, write this line:
File file;
int cardpin = 4;
We are going to use two text files, one for the temperature data and one for the count of high temperatures (for later)
This is the code that initializes the CCS
pinMode(cardpin, OUTPUT);
if (!SD.begin(cardpin)) {
Serial.println("SD card initialization failed");
}
if (SD.exists("data.txt")) {
Serial.println("data.txt exists.");
if (SD.remove("data.txt")) {
Serial.println("Successfully removed file.");
} else {
Serial.println("Could not remove data file.");
}
}
To edit the data file, do this:
Locate these lines of code
else{
if(degreesF <= 102.2){
lcd.print("Send person home");
}
else{
lcd.print("Person go to ER");
}
}
Under that, write these lines of code to edit data.txt file.
file = SD.open("data.txt", FILE_WRITE);
if (file) {
String fulldata = "Temp: "+String(degreesF);
file.println(fulldata);
file.close();
}
else {
Serial.println("Error in writing data file");
}
Now, put your hand over the sensor. The exact (temperature) output you get in serial and lcd should be the same as the DATA.txt file in the sd card.
In fact...
To connect to wifi, we use nodemcu module.
Specifically, it is the ESP8266 NodeMCU V1.0 ESP-12E WiFi Module.
Connect NodeMcu TX > Arduino 19/RX1 and NodeMcu RX > Arduino 18/TX1
CodeModifications
The arduino communicates to nodemcu on the Serial1 bus and nodemcu recives from arduino on its Serial bus.
Find this line of code
Serial.begin(9600);
Under that, write this line of code
Serial1.begin(115200);
115200 baud is needed for the wifi connection (for later).
Find this line of code
lcd.print("Temp: "+String(degreesF));
Under that, write this line of code
Serial1.println(degreesF);
Now open a new arduino sketch. (File>New)
Make sure to include the NodeMcu as an actuall board. Go to File> Preferences>Additional Boards Manager URLs. In that text box, put this:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
This will add the NodeMcu board as well as other boards.
This is the code for the NodeMcu.
Locate this line
// put your setup code here, to run once:
Under that, write these lines
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Locate this line
// put your main code here, to run repeatedly:
Under that, write these lines
if (Serial.available()) {
Serial.write(Serial.read());
}
UploadingCode
Make sure to disconnect RX/TX pins on NodeMcu. Upload would not work if these are connected. After upload is done, then replug them.
The NodeMcu should be set to default conditions.
Upload the code to the NodeMcu.
Then, upload the Arduino code to the Arduino.
Open the NodeMcu port.
What is being read on the Arduino should come in the NodeMcu COM port.
Setting up AWS free-tier account is very easy and so is setting AWS IoT connection. In this section, we will show you how to setup IoT in AWS. Login to AWS with your account credentials. Search for "AWS IoT" in Services, then click on it. In IoT page, expand "Manage" and select "Things".
Choose "Create" to new AWS IoT Thing.
Then, choose "Register a single AWS IoT thing"
Provide the name and other details and select "Next".
Generate certificates by selecting "Create certificates".
On the last step, save the certificates locally.
Also make sure to download the CA file.
AWS IoT rule consists of an SQL SELECT statement, a topic filter, and a rule action.
- Devices send information to AWS IoT by publishing messages to MQTT topics.
- The SQL SELECT statement allows you to extract data from an incoming MQTT message.
- The topic filter of an AWS IoT rule specifies one or more MQTT topics.
- The rule is triggered when an MQTT message that matches the topic filter is received on a topic.
- Rule actions allow you to take the information extracted from an MQTT message and send it to another AWS service. Rule actions are defined for AWS services like Amazon DynamoDB, AWS Lambda, Amazon SNS, and Amazon S3. By using a Lambda rule, you can call other AWS or third-party web services.
In the AWS IoT menu, select "Act" and on the Rules page, select "Create".
On the "Create a Rule" page, provide the name of the rule
On the SQL Query, enter the query or select the default
Choose Add Action
Here we will insert the message into a DynamoDB table.
On Configure Action, select the Database table if you have already created or choose to create a new resource (DynamoDB Table).
Choose "Create Table" on the DynamoDB page.
Provide table name. Enter the partition key id as a string and createdAt as a number. Select "Create" to create the table.
Return back to the "Create a Rule" page and select the new table created. Select "Create Rule". Now, you should be able to see the newly created rules.
Choose "Test" to test the rule that you have created on MQTT client page.
Enter the topic outTopic
and click "Subscribe to topic". Go to the "Publish" page and select "Publish to Topic". Your message will be saved to DynamoDB.
Note down the endpoint of MQTT. This is needed in the code. (for later)
The certificates needed to be converted to.der format so they can be uploaded to the NodeMcu. The best way to do this is through Openssl. We will walk you through how to install Openssl, and the commands you need to run.
Forlinux
To install on linux, run these commands to install openssl.
If system is based on yum, do
sudo yum install openssl
if based on apt, do
sudo apt-get install openssl
ForWindows
For windows, Visual C++ 2008 is a prerequisite. Please download it from here.
Download Openssl from here. Select 32 bit or 64 bit based on your system.
CommandsChange your directory to where your certificates are.
Run these commands to change the certificate name to cert.der, private.der and ca.der.
> openssl x509 -in xxxxxxxxxx-certificate.pem.crt -out cert.der -outform DER
> openssl rsa -in xxxxxxxxxx-private.pem.key -out private.der -outform DER
> openssl x509 -in AmazonRootCA1.pem -out ca.der -outform DER
Step 12: ESP8266 sketch data upload tool in ArduinoThe next step is to install Arduino ESP8266 filesystem uploader. which packs the sketch data folder into the SPIFFS filesystem image, and uploads the image to ESP8266 flash memory.
- Download the tool archive”ESP8266FS-0.4.0.zip” from the Git hub releases page.
- In your Arduino sketchbook directory, create
tools
directory if it doesn’t exist yet. You can find the location of your sketchbook directory in the Arduino IDE at File > Preferences > Sketchbook location. - Unpack the tool into
tools
directory (the path will look like<sketchbook directory>/tools/ESP8266FS/tool/esp8266fs.jar)
. - Restart Arduino IDE.
- Select “tools > ESP8266 Sketch Data Upload” will be there.
Please download, or copy-paste the source code found in the 'Code' area of this project. For the nodemcu, it is called "NodeMcuFinalCode"
Step 14: Building Alexa SkillOpen Alexa developer console. You will need to create Alexa/Amazon account. Create the account if you don’t have as it is free.
Select ‘Create Skill’.
Enter the name of the skill and select default language.
Choose “Custom” in the model and “Provision your own” and select the button “Create Skill”. Choose “Hello World Skill” as your template.
Once skill is created, choose JSON editor to modify the Intents, where you can directly update the JSON file and configure intents, slots and utterances.
Insert the following JSON Code:
{
"interactionModel": {
"languageModel": {
"invocationName": "community safety protector",
"intents": [
{
"name": "AMAZON.StartOverIntent",
"samples": []
},
{
"name": "AMAZON.RepeatIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": [
"help",
"help me"
]
},
{
"name": "AMAZON.StopIntent",
"samples": [
"stop"
]
},
{
"name": "AMAZON.CancelIntent",
"samples": [
"cancel"
]
},
{
"name": "AMAZON.YesIntent",
"samples": []
},
{
"name": "AMAZON.NoIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "GetTotal",
"slots": [
{
"name": "thisDate",
"type": "AMAZON.DATE"
}
],
"samples": [
"count for {thisDate}",
"what is the count of {thisDate}",
"Get the total for this {thisDate}"
]
}
],
"types": []
}
}
}
Select Build Model to build. This will build the model for Alexa Skills and will add intents, slots and utterances.
Now, we will create an associated Lambda function on AWS. You will need to create an AWS account, note that this is different from Alexa Developer account. AWS offers a one year of free tier with limited services.
To deploy lambda, we will utilize Serverless. For more information go to http://www.serverless.com/ to create a free account and install Serverless on your development environment.
In your development environment, create a new folder and create serverless project thru nodejs. Open Node.js command and execute the following command to create handler.js and serverless.yml
> serverless create --template aws-nodejs
The following is the code for handler.js
'use strict';
const AWS = require('aws-sdk');
const Alexa = require("alexa-sdk");
const lambda = new AWS.Lambda();
const dynamoDb = new AWS.DynamoDB.DocumentClient();
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context);
alexa.appId = "amzn1.ask.skill.XXXXXXXXXXXXXXXXXXXXXXXXXX";
alexa.registerHandlers(handlers);
alexa.execute();
};
const handlers = {
'LaunchRequest': function () {
this.emit('Prompt');
},
'Unhandled': function () {
this.emit('AMAZON.HelpIntent');
},
'GetTotal': function () {
var srchDate = this.event.request.intent.slots.thisDate.value;
var theDate01 = Date.parse(srchDate);
var theDate02 = theDate01+86400000;
var itemCount = 1200;
const params = {
TableName: 'TABLE_NAME',
FilterExpression: 'createdAt >= :startDT AND createdAt <= :endDT',
ExpressionAttributeValues: {
':startDT': theDate01,
':endDT': theDate02
}
};
console.log('Getting the count'+theDate01+' and '+theDate02,params);
const self = this;
dynamoDb.scan(params, function (err, data) {
itemCount = data.Count;
if(itemCount>0)
{
console.log('Total Items'+itemCount);
self.emit(':ask', 'On '+srchDate+', there were '+itemCount+' cases of high temperature');
}
else
{
self.emit(':ask', 'On '+srchDate+', there were no cases of high temperature');
}
});
},
'AMAZON.YesIntent': function () {
this.emit('Prompt');
},
'AMAZON.NoIntent': function () {
this.emit('AMAZON.StopIntent');
},
'Prompt': function () {
this.emit(':ask', 'Welcome to community safety protector alexa Q and A. You can ask how many cases there were on a specific day and safety precautions to take with the number of cases.');
},
'NoMatch': function () {
this.emit(':ask', 'Sorry, I couldn\'t understand.', 'Please say that again?');
},
'AMAZON.HelpIntent': function () {
const speechOutput = 'You can ask the number of scans and also ask for safety precautions';
const reprompt = 'Say Alexa to hear me back';
this.response.speak(speechOutput).listen(reprompt);
this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
this.response.speak('Goodbye!');
this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
this.response.speak('See you later!');
this.emit(':responseReady');
}
};
Replace alexa.appid with your Alexa Skill ID. Your Alexa Skill ID can be found by going to your Skill kit Dashboard by logging to https://developer.amazon.com/alexa/console/ask. Under your skill, select ‘View Skil ID’. Click and copy the skill ID.
The following is the code for serverless.yml
service: XXXXXX
provider:
name: aws
runtime: nodejs12.x
region: us-east-1
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "XXXXXXXXXXXXXXXXXXXX"
custom:
defaultStage: dev
profiles:
dev: serverless
prod: serverless
dynamodb:
start:
migrate: true
functions:
GetTotal:
handler: handler.handler
events:
- alexaSkill
Replace Resource:
with your dynamodb ARN.
Execute the following command to create package.json file and provide the necessary details.
> npm init
Save all files. Deploy lambda, find and copy its ARN.
> serverless deploy
Return back to Alexa developer console and select "End point" from the navigation menu, paste the copied ARN in "Default Region". Save Endpoints. This will bind Alexa Skill to Lambda in AWS.
Now, the project is complete. The Arduino code and NodeMcu code is in the "Code" section. We have also uploaded the serverless.yml, NodeJs, and JSON code there.
Video DemoHere is the video demo of the project. This shows how the Arduino communicates the NodeMcu, which communicates to DynamoDB. Alexa then will retrieve the data from DynamoDB.
Comments