Kittitouch Areerob
Published © LGPL

Automatic Vehicle Accident Alert System using AWS IoT

In vehicle accident, An alerting message which contains time and location automatically is sent to emergency agencies for relief the victim.

IntermediateFull instructions provided17,594

Things used in this project

Hardware components

Raspberry Pi 2 Model B
Raspberry Pi 2 Model B
×1
GPS receiver (generic)
×1
EW-7811Un - Edimax Wifi dongle
×1
Push Button
×1
USB to TTL convertor
×1
Radio-controlled Car
×1

Software apps and online services

AWS IoT
Amazon Web Services AWS IoT
AWS Lambda
Amazon Web Services AWS Lambda
AWS SNS
Amazon Web Services AWS SNS
AWS DynamoDB
Amazon Web Services AWS DynamoDB
AWS IAM
Amazon Web Services AWS IAM
Real Time Framework

Story

Read more

Schematics

System Overview

Hardware Schematic

Code

Lambda Function

JavaScript
Put it in Lambda function code section in the create Lambda function page
console.log('Loading function');

var AWS = require('aws-sdk');
var https = require('https');
var sns = new AWS.SNS();
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

exports.handler = function(event, context) {
    
    var appkey = 'X3hxTR';
    var privatekey = '5GH14gELwQXH';
    var channel = 'aws-iot';

    //Prepare latitude for generating Google Map hyperlink
    var latindex = event.state.reported.latitude.indexOf('.');
    var latitude = event.state.reported.latitude.slice(0,latindex-2)+'%'+event.state.reported.latitude.slice(latindex-2,event.state.reported.latitude.length);
    console.log("Latitude : "+latitude);
    //Prepare longitude for generating Google Map hyperlink
    var longindex = event.state.reported.longitude.indexOf('.');
    var longitude = event.state.reported.longitude.slice(0,latindex-2)+'%'+event.state.reported.longitude.slice(latindex-2,event.state.reported.longitude.length);
    console.log("Longtitude : "+longitude);
    //Prepare car's crashed time
    var timestamp = new Date(event.metadata.reported.car_number.timestamp*1000);
    console.log("Date : "+timestamp.toString());
    //Generate Alerting Message 
    var head = "Unfortunately, Your registered car has been crashed. We hope the following info will be helpful for you.\r\n\r\n";
    var car_number = "Car Number : " + event.state.reported.car_number +"\r\n";
    var location = "Location : http://maps.google.com/?q=" + latitude + ',' + longitude + "\r\n";
    var date = "Date : " +  timestamp.toString() + "\r\n";
    var emergency = "Emergency Services Number: Tourist Police(1155), Police(191) and Ambulance and Rescue(1554)";
    var alerting_message = head + car_number + location + date + emergency;
    //Send Alerting Message to Real Time Application
    var postBody = "AK=" + appkey + "&PK=" + privatekey + "&C=" + channel + "&M=" + alerting_message;
    var headers = {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': postBody.length
    };
    var options = {
      hostname: 'ortc-developers2-useast1-s0001.realtime.co',
      port: 443,
      path: '/send',
      method: 'POST',
      headers: headers
    };
    var req = https.request(options, function(res) {
        var body = '';
        res.setEncoding('utf8');
        res.on('data', function(chunk) {
            body += chunk;
        });
        res.on('end', function() {
            if(res.statusCode==201) {
                console.log('Message sent successfully to Realtime');
            } else {
                console.log('Error sending message to Realtime. Description: ', 
                body);
            }
            context.succeed(body);
        });
    });
    req.on('error', context.fail);
    req.write(postBody);
    req.end();
    //Send Alerting Message to SNS (Email)
    sns.publish({
        TopicArn: "arn:aws:sns:us-east-1:899237566099:carCrashSNS",
        Message: alerting_message
    }, function(err, data) {
        if(err) {
            console.error('error publishing to SNS');
            context.fail(err);
        } else {
            console.info('message published to SNS');
            context.done(null, data);
        }
    });
    //Insert Alerting information to DynamoDB
    var tableName = "CARCRASH_DB";
    dynamodb.putItem({
        "TableName": tableName,
        "Item" : {
            "CAR_NUMBER": {"S": event.state.reported.car_number },
            "DATE": {"S": timestamp.toString()},
            "LATITUDE": {"S": latitude },
            "LONGTITUDE": {"S": longitude }
        }
    }, function(err, data) {
        if (err) {
            context.done('error','putting item into dynamodb failed: '+err);
        }
        else {
            console.log('success: '+JSON.stringify(data, null, '  '));
        }
    });
};

Thing's Agent

C/C++
Download and make it on Raspberry Pi 2
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <memory.h>
#include <sys/time.h>
#include <limits.h>
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_shadow_json_data.h"
#include "aws_iot_config.h"
#include "aws_iot_mqtt_interface.h"
#include <wiringPi.h>
#include <string.h>

void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
                const char *pReceivedJsonDocument, void *pContextData) {

        if (status == SHADOW_ACK_TIMEOUT) {
                INFO("Update Timeout--");
        } else if (status == SHADOW_ACK_REJECTED) {
                INFO("Update RejectedXX");
        } else if (status == SHADOW_ACK_ACCEPTED) {
                INFO("Update Accepted !");
        }
}

char certDirectory[PATH_MAX + 1] = "../../certs";
char HostAddress[255] = AWS_IOT_MQTT_HOST;
uint32_t port = AWS_IOT_MQTT_PORT;
uint8_t numPubs = 5;
char SERIAL_DEV[13] = "/dev/ttyUSB0";

void parseInputArgsForConnectParams(int argc, char** argv) {
        int opt;

        while (-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) {
                switch (opt) {
                case 'h':
                        strcpy(HostAddress, optarg);
                        DEBUG("Host %s", optarg);
                        break;
                case 'p':
                        port = atoi(optarg);
                        DEBUG("arg %s", optarg);
                        break;
                case 'c':
                        strcpy(certDirectory, optarg);
                        DEBUG("cert root directory %s", optarg);
                        break;
                case 'n':
                        numPubs = atoi(optarg);
                        DEBUG("num pubs %s", optarg);
                        break;
                case '?':
                        if (optopt == 'c') {
                                ERROR("Option -%c requires an argument.", optopt);
                        } else if (isprint(optopt)) {
                                WARN("Unknown option `-%c'.", optopt);
                        } else {
                                WARN("Unknown option character `\\x%x'.", optopt);
                        }
                        break;
                default:
                        ERROR("ERROR in command line argument parsing");
                        break;
                }
        }

}

#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200

int main(int argc, char** argv) {
        int gpsp;               
        int serial_read;        
        
        IoT_Error_t rc = NONE_ERROR;
        int32_t i = 0;

        MQTTClient_t mqttClient;
        aws_iot_mqtt_init(&mqttClient);

        char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
        size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
        char *pJsonStringToUpdate;

        char car_number [] = "wc4443";
        jsonStruct_t car_numberHandler;
        car_numberHandler.cb = NULL;
        car_numberHandler.pKey = "car_number";
        car_numberHandler.pData = &car_number;
        car_numberHandler.type = SHADOW_JSON_STRING;

        jsonStruct_t latiHandler;
        latiHandler.cb = NULL;
        latiHandler.pKey = "latitude";
        latiHandler.type = SHADOW_JSON_STRING;

        jsonStruct_t longiHandler;
        longiHandler.cb = NULL;
        longiHandler.pKey = "longitude";
        longiHandler.type = SHADOW_JSON_STRING;

        char rootCA[PATH_MAX + 1];
        char clientCRT[PATH_MAX + 1];
        char clientKey[PATH_MAX + 1];
        char CurrentWD[PATH_MAX + 1];
        char cafileName[] = AWS_IOT_ROOT_CA_FILENAME;
        char clientCRTName[] = AWS_IOT_CERTIFICATE_FILENAME;
        char clientKeyName[] = AWS_IOT_PRIVATE_KEY_FILENAME;

        parseInputArgsForConnectParams(argc, argv);

        INFO("\nAWS IoT SDK Version(dev) %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);

        int PIN=2;
        wiringPiSetup () ;
        pinMode (PIN, INPUT) ;

        INFO("GPIO Setup using PIN : %d\n", PIN);

        getcwd(CurrentWD, sizeof(CurrentWD));
        sprintf(rootCA, "%s/%s/%s", CurrentWD, certDirectory, cafileName);
        sprintf(clientCRT, "%s/%s/%s", CurrentWD, certDirectory, clientCRTName);
        sprintf(clientKey, "%s/%s/%s", CurrentWD, certDirectory, clientKeyName);
        
        DEBUG("Using rootCA %s", rootCA);
        DEBUG("Using clientCRT %s", clientCRT);
        DEBUG("Using clientKey %s", clientKey);

        ShadowParameters_t sp = ShadowParametersDefault;
        sp.pMyThingName = AWS_IOT_MY_THING_NAME;
        sp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
        sp.pHost = HostAddress;
        sp.port = port;
        sp.pClientCRT = clientCRT;
        sp.pClientKey = clientKey;
        sp.pRootCA = rootCA;

        INFO("Shadow Init");
        rc = aws_iot_shadow_init(&mqttClient);

        INFO("Shadow Connect");
        rc = aws_iot_shadow_connect(&mqttClient, &sp);

        if (NONE_ERROR != rc) {
                ERROR("Shadow Connection Error %d", rc);
        }

        if (NONE_ERROR != rc) {
                ERROR("Shadow Register Delta Error");
        }
        while (NONE_ERROR == rc) {
        if(digitalRead(PIN)){
                char serial_read_char = '\0';
                char gpsmsg[2000] ;
                char lati_read[10];
                char longi_read[11];
                //GPS
                gpsp = serialOpen (SERIAL_DEV,9600);
               while(strcmp(gpsmsg,"$GPRMC")!=0){
                        serial_read = serialGetchar(gpsp);
                        serial_read_char = (char)serial_read;
                        if(serial_read_char!='$'){
                                strncat(gpsmsg,&serial_read_char,1);
                        }else{
                                memset(gpsmsg,0,2000);
                                strncat(gpsmsg,&serial_read_char,1);
                        }
                }
                while((char)serial_read!='*'){
                        serial_read = serialGetchar(gpsp);
                        serial_read_char = (char)serial_read;
                        strncat(gpsmsg,&serial_read_char,1);
                }
                DEBUG("GPS Sentense : %s",gpsmsg);
                char * pch;
                int tokcount = 1;
                pch = strtok (gpsmsg,",");
                while (pch != NULL){
                        pch = strtok (NULL, ",");
                        if(tokcount==3){
                                strcpy(lati_read,pch);
                        }else if(tokcount==5){
                                strcpy(longi_read,pch);
                        }
                        tokcount++;
                }
                DEBUG(" LATITUDE : %s      LONGITUDE : %s",lati_read,longi_read);
                latiHandler.pData = lati_read;
                longiHandler.pData = longi_read;
                rc = aws_iot_shadow_yield(&mqttClient, 200);
                INFO("\n=======================================================================================\n");
                INFO("On Device: Car Number %s", car_number);
                rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
                if (rc == NONE_ERROR) {
                        rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3,&car_numberHandler ,&latiHandler, &longiHandler);           $
                        if (rc == NONE_ERROR) {
                                rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
                                if (rc == NONE_ERROR) {
                                        INFO("Update Shadow: %s", JsonDocumentBuffer);
                                        rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer, ShadowUpdateStatusCallback,
                                        NULL, 4, true);
                                }
                        }
                }
                INFO("*****************************************************************************************\n");
                sleep(60);
        }
        }

        if (NONE_ERROR != rc) {
                ERROR("An error occurred in the loop %d", rc);
        }

        INFO("Disconnecting");
        rc = aws_iot_shadow_disconnect(&mqttClient);

        if (NONE_ERROR != rc) {
                ERROR("Disconnect error %d", rc);
        }

        return rc;
}


        

Credits

Kittitouch Areerob

Kittitouch Areerob

1 project • 24 followers

Comments