Things used in this project

Hardware components:
Photon new
Particle Photon
×1
DHT22 Temperature Sensor
×1
DC Power Plug Supply Adapter Metal Jack Socket
×1
Project Box
×1
Dupont Housing and Pins
×1
Wire
×1
Power Supply
×1
Osh park
OSH Park Custom fabricated PCB
×1
Software apps and online services:
Particle Console
Particle Build - IDE
Rds
Amazon Web Services AWS RDS
Screen%20shot%202015 07 20%20at%206.10.26%20pm
Amazon Web Services AWS Lambda
Screen%20shot%202015 07 20%20at%206.13.19%20pm
Amazon Web Services AWS Elastic Beanstalk
Amazon Web Services API Gateway
IFTTT Particle Chanel
Particle iPhone App
MySQL Workbench
Hand tools and fabrication machines:
09507 01
Soldering iron (generic)
Drill (generic)
Wire Stripper (generic)

Custom parts and enclosures

Web Page
Mlhbimordcprmtsmbhl8
IFTTT Recipe
Configure the Particle Channel, configure the SMS channel, and you're good to go
I80hhido74lwj9igungp

Schematics

Breadboard Diagram
Jxcqmypgj8qczgkz8zq1
Schematic
8vvgefhlnh8md3hpznit
Eagle Schematic
Photon was included during design. Once PCB design was complete, Photon was replaced by relevant male headers. This kept PCB size down, which made it less expensive to manufacture.
ke1YWKQnn04UkptjrZOT.sch
Eagle Board File
Photon was included during design. Once PCB design was complete, Photon was replaced by relevant male headers. This kept PCB size down, which made it less expensive to manufacture.
6o3QbIxP5YscxpmI5aE4.brd

Code

Photon SketchArduino
This is the sketch that is flashed onto the Photon
// This #include statement was automatically added by the Particle IDE.
#include "DHT.h"

//
// Copyright (c) 2016 Jon Hobbs
//
// Built on top of other's hard work, Espcially Nic Jansma
//   Original sketch Copyright (c) 2016 Nic Jansma, http://nicj.net
//      https://github.com/nicjansma/dht-logger
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// *****************
//
// Key changes from Nic's sketch:
//      * Configured for my device
//      * Removed functionality for posting data to Adafruit, ThingSpeak, and generic HTTP
//      * Added alarm functionality
//      * Added zero'd out publish if sensor reading fails
//      * Added funtion and Particle variable to handle web hook response event and spark\status events
//
// ****************
//
// Includes
//
#include "application.h"
#include <string>

//
// Configuration
//

// device & event name
#define DEVICE_NAME "Weather_Node_1"
#define PARTICLE_EVENT_NAME "dht-logger-log"

// sensor type: [DHT11, DHT22, DHT21, AM2301]
#define DHTTYPE DHT11

// which digital pin for the DHT
#define DHTPIN D3

// which digital pin for the Photon/Spark Core/Electron LED
#define LEDPIN D7

// whether to use Farenheit instead of Celsius
#define USE_FARENHEIT 1

// min/max values (sanity checks)
#define MIN_TEMPERATURE -30
#define MAX_TEMPERATURE 120

#define MIN_HUMIDITY 0
#define MAX_HUMIDITY 100

// sensor sending interval (seconds)
#define SEND_INTERVAL 900  // 15 minutes


// Particle alarms
#define PARTICLE_TEMP_HIGH_ALARM 1  // enables high temp alarm
#define PARTICLE_TEMP_HIGH_ALARM_NAME "High-Temp-Alarm"
#define PARTICLE_TEMP_HIGH_ALARM_THRESHOLD 80  //alarm event will be sent if temp > 80

//
// Locals
//
TCPClient tcpClient;

DHT dht(DHTPIN, DHTTYPE);

float humidity;
float temperature;
float heatIndex;

char humidityString[10];
char temperatureString[10];
char heatIndexString[10];
char respEvent[100];

int failed = 0;

// last time since we sent sensor readings
int lastUpdate = 0;

// for Particle.publish payloads
char payload[1024];

/**
 * Handle web hook to AWS API
 *   This function is fired every time the AWS web hook publishes
 *   a response event.  If that response is not a 'success'
 *   message, then republish the current data, which will re-trigger
 *   the web hook.
 */
void myHandler(const char *event, const char *data) {
  // Handle the integration response
    strcpy(respEvent, event);  //converts the event name to a string
    
  if (strstr(event,"hook-response/dht-logger-log") != NULL)  //looks for a specific web hook event
  {
      if (strstr(data, "Success") == NULL)  //web hook event data will contain "Success" if successful
      {                                     //so if strstr is null, "Success" was not in the data
        sprintf(payload,
            "{\"device\":\"%s\",\"temperature\":%.2f,\"humidity\":%.2f,\"heatIndex\":%.2f}",
            DEVICE_NAME,
            temperature,
            humidity,
            heatIndex);
        Particle.publish(PARTICLE_EVENT_NAME, payload, 60, PRIVATE);  //re-publish current data
      }
      else
      {
          Particle.publish("AWS-API-Webhook-Status", "Success", 60, PRIVATE);  //web hook was successful so publish status as an event
      }
    }
}

/**
 * Setup
 */
void setup() {
    pinMode(LEDPIN, OUTPUT);
    digitalWrite(LEDPIN, HIGH);

    // configure Particle variables - float isn't accepted, so we have to use string versions
    // these are the variables that are exposed to the Particle cloud
    Particle.variable("temperature", &temperatureString[0], STRING);
    Particle.variable("humidity", &humidityString[0], STRING);
    Particle.variable("heatIndex", &heatIndexString[0], STRING);
    Particle.variable("status", &failed, INT);
    Particle.variable("respEvent", &respEvent[0], STRING);  //event name - for troubleshooting

    // start the DHT sensor
    dht.begin();

    // startup event
    Particle.subscribe("hook-response/dht-logger-log", myHandler, MY_DEVICES);  //subscribe to web hook response event
    Particle.subscribe("spark/status", myHandler, MY_DEVICES);  //subscribe to status events.  
    sprintf(payload,
            "{\"device\":\"%s\",\"state\":\"starting\"}",
            DEVICE_NAME);

    Particle.publish(PARTICLE_EVENT_NAME, payload, 60, PRIVATE);  //publish a "starting up" event

    // run the first measurement
    loop();
}

/**
 * Event loop
 */
void loop() {
    int now = Time.now();

    // only run every SEND_INTERVAL seconds
    if (now - lastUpdate < SEND_INTERVAL) {
        return;
    }

    // turn on LED when updating
    digitalWrite(LEDPIN, HIGH);
    lastUpdate = now;
    failed = 0;

    // read humidity and temperature values
    humidity = dht.readHumidity();
    temperature = dht.readTemperature(USE_FARENHEIT);

    if (temperature == NAN
        || humidity == NAN
        || temperature > MAX_TEMPERATURE
        || temperature < MIN_TEMPERATURE
        || humidity > MAX_HUMIDITY
        || humidity < MIN_HUMIDITY) {
        // if any sensor failed, publish a zero'd out event.
        failed = 1;
        sprintf(payload,
            "{\"device\":\"%s\",\"temperature\":%.2f,\"humidity\":%.2f,\"heatIndex\":%.2f}",
            DEVICE_NAME,
            0.0,
            0.0,
            0.0);
        //#if PARTICLE_EVENT
        Particle.publish(PARTICLE_EVENT_NAME, payload, 60, PRIVATE);
        //#endif

    } else { //we successfully retrieved valid data from the sensor, so publish it!
        failed = 0;

        // calculate the heat index
        heatIndex = dht.computeHeatIndex(temperature, humidity, USE_FARENHEIT);

        // convert floats to strings for Particle variables
        sprintf(temperatureString, "%.2f", temperature);
        sprintf(humidityString, "%.2f", humidity);
        sprintf(heatIndexString, "%.2f", heatIndex);

        sprintf(payload,
            "{\"device\":\"%s\",\"temperature\":%.2f,\"humidity\":%.2f,\"heatIndex\":%.2f}",
            DEVICE_NAME,
            temperature,
            humidity,
            heatIndex);

        //#if PARTICLE_EVENT
            Particle.publish(PARTICLE_EVENT_NAME, payload, 60, PRIVATE);
        //#endif

        #if PARTICLE_TEMP_HIGH_ALARM  //if alarm is enabled, then examine the threshold and publish alarm event if warrented.
            if (temperature > PARTICLE_TEMP_HIGH_ALARM_THRESHOLD)
            {
                Particle.publish(PARTICLE_TEMP_HIGH_ALARM_NAME, payload, 60, PRIVATE);
            }
        #endif
    }

    // done updating
    digitalWrite(LEDPIN, LOW);
}
Database Schema Create StatementSQL
The SQL statement that creates our database/schema in RDS
CREATE DATABASE `WeatherNodeLog` /*!40100 DEFAULT CHARACTER SET latin1 */;
Table Create StatementsSQL
The SQL statements that create the 2 tables we use to store our log data.
CREATE TABLE `LocalNodeLog` (
  `LocalNodeLogId` int(11) NOT NULL AUTO_INCREMENT,
  `NodeMAC` varchar(20) NOT NULL,
  `LocalNodeTemp` float DEFAULT NULL,
  `LocalNodeHumidity` float DEFAULT NULL,
  `LogTimeStamp` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`LocalNodeLogId`)
) ENGINE=InnoDB AUTO_INCREMENT=15966 DEFAULT CHARSET=latin1;


CREATE TABLE `LocalNode` (
  `LocalNodeId` int(11) NOT NULL AUTO_INCREMENT,
  `LocalNodeMAC` varchar(20) DEFAULT NULL,
  `LocalNodeLocation` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`LocalNodeId`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1;
Lambda FunctionJavaScript
This is the Node.JS code that receives data from Particle cloud web hook and inserts into a table in a MySQL database. Note that things like connect strings, usernames, passwords and other security-related bits of code of been masked to protect the innocent.
var mac;
var temp;
var humid;
var payload;

console.log('Loading');

exports.handler = function (event, context, callback) {

    if (event !== null) 
    {
        console.log('event = ' + JSON.stringify(event));
        mac = event.MAC;
        temp = event.Temp;
        humid = event.Humid;
    }
    else 
    {
        console.log('No event object');
    }
    var mysql = require('mysql');
    var connection = mysql.createConnection({
        host: 'xxx.xxxxxxxxx.xxxxxxx.rds.amazonaws.com',
        user: '<user name>',
        password: '<Password>',
        database: 'Weather'
    });
    connection.connect();

    var qry = "INSERT INTO Weather.LocalNodeLog (NodeMAC, LocalNodeTemp, LocalNodeHumidity) VALUES ('" + mac + "','" + temp + "','" + humid + "');"
    console.log(qry);
    connection.query(qry, function (err, rows, fields) {
        if (!err) 
        {
            console.log('Return is: ', JSON.stringify(rows));
            output = JSON.stringify(rows);
            context.done(null, 'Log Node Successful');  // SUCCESS with message
            callback(null, output);
        }
        else
            console.log('Error while performing Query.');
        context.done("err", "query failure");
    });

    connection.end();
    
};

Credits

Studio%20test%20session 103t
Jon Hobbs

Just a Minnesota kid hanging out in Kansas

Thanks to Nic Jansma.

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Farm Irrigation System
Advanced
  • 532
  • 11

Full instructions

A contribution to the Internet of Plants.

Temperature and Humidity Notifier
Advanced
  • 21
  • 0

It is a notifier with temperature and humidity sensor in it. The LED screen will show the temperature and humidity at present.

Mailbox 2.0
Advanced
  • 3,620
  • 79

Work in progress

Real time notifications for when your precious packages and letters arrive.

Mailbox 2.0

Team CKTS

Networked RGB Wi-Fi Decorative Touch Lights
Advanced
  • 10,182
  • 132

Full instructions

Easy to use Wi-Fi enabled touch lights that network to give you a beautiful and unobtrusive way to stay connected with the people you love.

Use the Force... Or your Brainwaves?
Advanced
  • 15,812
  • 68

Full instructions

Thought controlled system with personal webserver and 3 working functions: robot controller, home automation and PC mouse controller.

The Minimalist Thermostat
Advanced
  • 5,115
  • 33

Full instructions

A thermostat you won't see

Add projectSign up / Login