Example program for MultiTech Dragonfly using Grove moisture sensor and Grove button.

Dependencies:   MbedJSONValue mbed mtsas

Fork of MultiTech_Dragonfly_2015_ATT_Gov_Solutions_Hackathon_Example by Multi-Hackers

main.cpp

Committer:
mfiore
Date:
2015-09-27
Revision:
6:d6cf1bf4130e
Parent:
5:a946ef74a8c4

File content as of revision 6:d6cf1bf4130e:

/*************************************************************************
 * Dragonfly Example program for 2015 AT&T Government Solutions Hackathon
 * 
 * The following hardware is required to successfully run this program:
 *   - MultiTech UDK2 (4" square white PCB with Arduino headers, antenna
 *     connector, micro USB ports, and 40-pin connector for Dragonfly)
 *   - MultiTech Dragonfly (1"x2" green PCB with Telit radio)
 *   - Seeed Studio Base Shield
 *   - Grove moisture sensor (to connect to Base Shield)
 *   - Grove button (to connect to Base Shield)
 *
 * What this program does:
 *   - reads data from the moisture sensor on a periodic basis
 *   - prints all sensor data to debug port on a periodic basis
 *   - optionally send a SMS containing sensor data when the Grove Button
 *     is pushed
 *       - you need to set the "phone_number" field
 *   - optionally sends sensor data to AT&T M2X cloud platform (user must
 *     create own M2X account and configure a device)
 *       - you need to set the "m2x_api_key" field and the "m2x_device_id"
 *         field based on your M2X account for this to work
 *       - you need to set the "do_cloud_post" flag to true for this to
 *         work
 *
 * Setup:
 *   - Correctly insert SIM card into Dragonfly
 *   - Seat the Dragonfly on the UDK2 board
 *   - Connect an antenna to the connector on the Dragonfly labled "M"
 *   - Stack the Base Shield on the UDK2 Arduino headers
 *   - Connect the Grove button to the D8 socket on the Base Shield
 *   - Connect the Grove moisture sensor to the A0 socket on the Base
 *     Shield
 *   - Make sure the reference voltage selector switch (next to the A0
 *     socket) is switched to 5V so you get accurate analog readings
 *   - Plug in the power cable
 *   - Plug a micro USB cable into the port below and slightly to the
 *     left of the Dragonfly (NOT the port on the Dragonfly)
 *
 * Go have fun and make something cool!
 *
 ************************************************************************/
 
#include "mbed.h"
#include "mtsas.h"
#include "MbedJSONValue.h"
#include "HTTPJson.h"
#include <string>

// Debug serial port
static Serial debug(USBTX, USBRX);

// MTSSerialFlowControl - serial link between processor and radio
static MTSSerialFlowControl* io;

// Cellular - radio object for cellular operations (SMS, TCP, etc)
Cellular* radio;

// APN associated with SIM card
// this APN should work for the AT&T SIM that came with your Dragonfly
//static const std::string apn = "";
static const std::string apn = "broadband";

// Phone number to send SMS messages to
// just change the x digits - the 1 needs to stay!
static const std::string phone_number = "1xxxxxxxxxx";

// see https://m2x.att.com/developer/documentation/v2/overview for M2X API documentation
// M2X device ID
static const std::string m2x_device_id = "";

// M2X primary API key
static const std::string m2x_api_key = "";

// set to true if you want to post to the cloud
// you need to have you M2X account set up properly for this to work?
//bool do_cloud_post = false;
bool do_cloud_post = true;

std::string url = "http://api-m2x.att.com/v2/devices/" + m2x_device_id + "/update";

// Moisture sensor
AnalogIn moisture_sensor(A0);

// Button
InterruptIn button(D8);
bool button_pressed = false;

// variables for sensor data
float moisture_percent;

// misc variables
static char wall_of_dash[] = "--------------------------------------------------";
bool radio_ok = false;
static int thpm_interval_ms = 2000;
static int print_interval_ms = 10000;
static int post_interval_ms = 30000;
int debug_baud = 115200;

// function prototypes
bool init_mtsas();
void read_moisture();
void button_irq();

// main
int main() {
    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
    debug.baud(debug_baud);
    logInfo("starting...");
    
    radio_ok = init_mtsas();
    if (! radio_ok)
        logError("MTSAS init failed");
    else
        logInfo("MTSAS is ok");
        
    button.fall(&button_irq);
        
    Timer thpm_timer;
    Timer print_timer;
    Timer post_timer;
    
    thpm_timer.start();
    print_timer.start();
    post_timer.start();
    
    while (true) {
        
        if (thpm_timer.read_ms() > thpm_interval_ms) {
            read_moisture();
            thpm_timer.reset();
        }
        
        if (print_timer.read_ms() > print_interval_ms) {
            logDebug("%s", wall_of_dash);
            logDebug("SENSOR DATA");
            logDebug("moisture: %f%%", moisture_percent);
            logDebug("%s", wall_of_dash);
            print_timer.reset();
        }
        
        if (button_pressed) {
            logInfo("Button was pressed");
            button_pressed = false;
            if (radio_ok) {
                MbedJSONValue sms_json;
                string sms_str;
                
                sms_json["moisture_percent"] = moisture_percent;
                
                sms_str = "SENSOR DATA:\n";
                sms_str += sms_json.serialize();
                
                logDebug("sending SMS to %s:\r\n%s", phone_number.c_str(), sms_str.c_str());
                Code ret = radio->sendSMS(phone_number, sms_str);
                if (ret != MTS_SUCCESS)
                    logError("sending SMS failed");
            }
        }
        
        if (post_timer.read_ms() > post_interval_ms && do_cloud_post) {
            if (radio->connect()) {
                logDebug("posting sensor data");

                HTTPClient http;
                MbedJSONValue http_json_data;
                std::string http_json_str;
                std::string m2x_header = "X-M2X-KEY: " + m2x_api_key + "\r\n";
                int ret;
                char http_response_buf[256];
                HTTPText http_response(http_response_buf, sizeof(http_response_buf));
                
                // moisture is a stream ID for my device in M2X
                // modify this to match your streams or give your stream the same name
                http_json_data["values"]["moisture"] = moisture_percent;
                http_json_str = http_json_data.serialize();
                
                // add extra header with M2X API key
                http.setHeader(m2x_header.c_str());
                
                HTTPJson http_json((char*)  http_json_str.c_str());
                ret = http.post(url.c_str(), http_json, &http_response);
                if (ret != HTTP_OK)
                    logError("posting data to cloud failed: [%d][%s]", ret, http_response_buf);
                else
                    logDebug("post result [%d][%s]", http.getHTTPResponseCode(), http_response_buf);
                
                radio->disconnect();
            } else {
                logError("establishing PPP link failed");
            }
            
            post_timer.reset();
        }
        
        wait_ms(10);
    }
}

// init functions
bool init_mtsas() {
    io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
    if (! io)
        return false;
        
    io->baud(115200);
    radio = CellularFactory::create(io);
    if (! radio)
        return false;
        
    Code ret = radio->setApn(apn);
    if (ret != MTS_SUCCESS)
        return false;
        
    Transport::setTransport(radio);
        
    return true;
}

// Sensor data acquisition functions

void read_moisture() {
    moisture_percent = moisture_sensor * 100.0;
}

void button_irq() {
    button_pressed = true;
}