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

Committer:
mfiore
Date:
Sun Sep 27 02:05:19 2015 +0000
Revision:
6:d6cf1bf4130e
Parent:
5:a946ef74a8c4
remove all code for ST MEMs board

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:a44e71488e1f 1 /*************************************************************************
mfiore 0:a44e71488e1f 2 * Dragonfly Example program for 2015 AT&T Government Solutions Hackathon
mfiore 0:a44e71488e1f 3 *
mfiore 0:a44e71488e1f 4 * The following hardware is required to successfully run this program:
mfiore 0:a44e71488e1f 5 * - MultiTech UDK2 (4" square white PCB with Arduino headers, antenna
mfiore 0:a44e71488e1f 6 * connector, micro USB ports, and 40-pin connector for Dragonfly)
mfiore 0:a44e71488e1f 7 * - MultiTech Dragonfly (1"x2" green PCB with Telit radio)
mfiore 0:a44e71488e1f 8 * - Seeed Studio Base Shield
mfiore 0:a44e71488e1f 9 * - Grove moisture sensor (to connect to Base Shield)
mfiore 0:a44e71488e1f 10 * - Grove button (to connect to Base Shield)
mfiore 0:a44e71488e1f 11 *
mfiore 0:a44e71488e1f 12 * What this program does:
mfiore 6:d6cf1bf4130e 13 * - reads data from the moisture sensor on a periodic basis
mfiore 0:a44e71488e1f 14 * - prints all sensor data to debug port on a periodic basis
mfiore 0:a44e71488e1f 15 * - optionally send a SMS containing sensor data when the Grove Button
mfiore 5:a946ef74a8c4 16 * is pushed
mfiore 5:a946ef74a8c4 17 * - you need to set the "phone_number" field
mfiore 4:730b61258422 18 * - optionally sends sensor data to AT&T M2X cloud platform (user must
mfiore 4:730b61258422 19 * create own M2X account and configure a device)
mfiore 5:a946ef74a8c4 20 * - you need to set the "m2x_api_key" field and the "m2x_device_id"
mfiore 5:a946ef74a8c4 21 * field based on your M2X account for this to work
mfiore 5:a946ef74a8c4 22 * - you need to set the "do_cloud_post" flag to true for this to
mfiore 5:a946ef74a8c4 23 * work
mfiore 0:a44e71488e1f 24 *
mfiore 0:a44e71488e1f 25 * Setup:
mfiore 0:a44e71488e1f 26 * - Correctly insert SIM card into Dragonfly
mfiore 0:a44e71488e1f 27 * - Seat the Dragonfly on the UDK2 board
mfiore 0:a44e71488e1f 28 * - Connect an antenna to the connector on the Dragonfly labled "M"
mfiore 0:a44e71488e1f 29 * - Stack the Base Shield on the UDK2 Arduino headers
mfiore 0:a44e71488e1f 30 * - Connect the Grove button to the D8 socket on the Base Shield
mfiore 0:a44e71488e1f 31 * - Connect the Grove moisture sensor to the A0 socket on the Base
mfiore 0:a44e71488e1f 32 * Shield
mfiore 3:f6bceb9e5e1a 33 * - Make sure the reference voltage selector switch (next to the A0
mfiore 3:f6bceb9e5e1a 34 * socket) is switched to 5V so you get accurate analog readings
mfiore 0:a44e71488e1f 35 * - Plug in the power cable
mfiore 0:a44e71488e1f 36 * - Plug a micro USB cable into the port below and slightly to the
mfiore 0:a44e71488e1f 37 * left of the Dragonfly (NOT the port on the Dragonfly)
mfiore 0:a44e71488e1f 38 *
mfiore 0:a44e71488e1f 39 * Go have fun and make something cool!
mfiore 0:a44e71488e1f 40 *
mfiore 0:a44e71488e1f 41 ************************************************************************/
mfiore 0:a44e71488e1f 42
mfiore 0:a44e71488e1f 43 #include "mbed.h"
mfiore 0:a44e71488e1f 44 #include "mtsas.h"
mfiore 0:a44e71488e1f 45 #include "MbedJSONValue.h"
mfiore 5:a946ef74a8c4 46 #include "HTTPJson.h"
mfiore 0:a44e71488e1f 47 #include <string>
mfiore 0:a44e71488e1f 48
mfiore 0:a44e71488e1f 49 // Debug serial port
mfiore 0:a44e71488e1f 50 static Serial debug(USBTX, USBRX);
mfiore 0:a44e71488e1f 51
mfiore 0:a44e71488e1f 52 // MTSSerialFlowControl - serial link between processor and radio
mfiore 1:a049d113e250 53 static MTSSerialFlowControl* io;
mfiore 0:a44e71488e1f 54
mfiore 0:a44e71488e1f 55 // Cellular - radio object for cellular operations (SMS, TCP, etc)
mfiore 0:a44e71488e1f 56 Cellular* radio;
mfiore 0:a44e71488e1f 57
mfiore 0:a44e71488e1f 58 // APN associated with SIM card
mfiore 4:730b61258422 59 // this APN should work for the AT&T SIM that came with your Dragonfly
mfiore 4:730b61258422 60 //static const std::string apn = "";
mfiore 4:730b61258422 61 static const std::string apn = "broadband";
mfiore 0:a44e71488e1f 62
mfiore 0:a44e71488e1f 63 // Phone number to send SMS messages to
mfiore 5:a946ef74a8c4 64 // just change the x digits - the 1 needs to stay!
mfiore 2:955a63247721 65 static const std::string phone_number = "1xxxxxxxxxx";
mfiore 0:a44e71488e1f 66
mfiore 5:a946ef74a8c4 67 // see https://m2x.att.com/developer/documentation/v2/overview for M2X API documentation
mfiore 5:a946ef74a8c4 68 // M2X device ID
mfiore 4:730b61258422 69 static const std::string m2x_device_id = "";
mfiore 5:a946ef74a8c4 70
mfiore 5:a946ef74a8c4 71 // M2X primary API key
mfiore 5:a946ef74a8c4 72 static const std::string m2x_api_key = "";
mfiore 5:a946ef74a8c4 73
mfiore 5:a946ef74a8c4 74 // set to true if you want to post to the cloud
mfiore 5:a946ef74a8c4 75 // you need to have you M2X account set up properly for this to work?
mfiore 5:a946ef74a8c4 76 //bool do_cloud_post = false;
mfiore 5:a946ef74a8c4 77 bool do_cloud_post = true;
mfiore 5:a946ef74a8c4 78
mfiore 5:a946ef74a8c4 79 std::string url = "http://api-m2x.att.com/v2/devices/" + m2x_device_id + "/update";
mfiore 4:730b61258422 80
mfiore 0:a44e71488e1f 81 // Moisture sensor
mfiore 0:a44e71488e1f 82 AnalogIn moisture_sensor(A0);
mfiore 0:a44e71488e1f 83
mfiore 0:a44e71488e1f 84 // Button
mfiore 2:955a63247721 85 InterruptIn button(D8);
mfiore 1:a049d113e250 86 bool button_pressed = false;
mfiore 0:a44e71488e1f 87
mfiore 0:a44e71488e1f 88 // variables for sensor data
mfiore 0:a44e71488e1f 89 float moisture_percent;
mfiore 0:a44e71488e1f 90
mfiore 0:a44e71488e1f 91 // misc variables
mfiore 0:a44e71488e1f 92 static char wall_of_dash[] = "--------------------------------------------------";
mfiore 0:a44e71488e1f 93 bool radio_ok = false;
mfiore 3:f6bceb9e5e1a 94 static int thpm_interval_ms = 2000;
mfiore 5:a946ef74a8c4 95 static int print_interval_ms = 10000;
mfiore 5:a946ef74a8c4 96 static int post_interval_ms = 30000;
mfiore 0:a44e71488e1f 97 int debug_baud = 115200;
mfiore 0:a44e71488e1f 98
mfiore 0:a44e71488e1f 99 // function prototypes
mfiore 0:a44e71488e1f 100 bool init_mtsas();
mfiore 0:a44e71488e1f 101 void read_moisture();
mfiore 0:a44e71488e1f 102 void button_irq();
mfiore 0:a44e71488e1f 103
mfiore 0:a44e71488e1f 104 // main
mfiore 0:a44e71488e1f 105 int main() {
mfiore 0:a44e71488e1f 106 mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
mfiore 0:a44e71488e1f 107 debug.baud(debug_baud);
mfiore 0:a44e71488e1f 108 logInfo("starting...");
mfiore 0:a44e71488e1f 109
mfiore 0:a44e71488e1f 110 radio_ok = init_mtsas();
mfiore 0:a44e71488e1f 111 if (! radio_ok)
mfiore 0:a44e71488e1f 112 logError("MTSAS init failed");
mfiore 0:a44e71488e1f 113 else
mfiore 0:a44e71488e1f 114 logInfo("MTSAS is ok");
mfiore 0:a44e71488e1f 115
mfiore 1:a049d113e250 116 button.fall(&button_irq);
mfiore 0:a44e71488e1f 117
mfiore 3:f6bceb9e5e1a 118 Timer thpm_timer;
mfiore 1:a049d113e250 119 Timer print_timer;
mfiore 4:730b61258422 120 Timer post_timer;
mfiore 0:a44e71488e1f 121
mfiore 3:f6bceb9e5e1a 122 thpm_timer.start();
mfiore 1:a049d113e250 123 print_timer.start();
mfiore 4:730b61258422 124 post_timer.start();
mfiore 1:a049d113e250 125
mfiore 0:a44e71488e1f 126 while (true) {
mfiore 0:a44e71488e1f 127
mfiore 3:f6bceb9e5e1a 128 if (thpm_timer.read_ms() > thpm_interval_ms) {
mfiore 3:f6bceb9e5e1a 129 read_moisture();
mfiore 3:f6bceb9e5e1a 130 thpm_timer.reset();
mfiore 0:a44e71488e1f 131 }
mfiore 0:a44e71488e1f 132
mfiore 0:a44e71488e1f 133 if (print_timer.read_ms() > print_interval_ms) {
mfiore 0:a44e71488e1f 134 logDebug("%s", wall_of_dash);
mfiore 0:a44e71488e1f 135 logDebug("SENSOR DATA");
mfiore 0:a44e71488e1f 136 logDebug("moisture: %f%%", moisture_percent);
mfiore 0:a44e71488e1f 137 logDebug("%s", wall_of_dash);
mfiore 0:a44e71488e1f 138 print_timer.reset();
mfiore 0:a44e71488e1f 139 }
mfiore 0:a44e71488e1f 140
mfiore 1:a049d113e250 141 if (button_pressed) {
mfiore 0:a44e71488e1f 142 logInfo("Button was pressed");
mfiore 1:a049d113e250 143 button_pressed = false;
mfiore 0:a44e71488e1f 144 if (radio_ok) {
mfiore 0:a44e71488e1f 145 MbedJSONValue sms_json;
mfiore 0:a44e71488e1f 146 string sms_str;
mfiore 0:a44e71488e1f 147
mfiore 0:a44e71488e1f 148 sms_json["moisture_percent"] = moisture_percent;
mfiore 0:a44e71488e1f 149
mfiore 2:955a63247721 150 sms_str = "SENSOR DATA:\n";
mfiore 0:a44e71488e1f 151 sms_str += sms_json.serialize();
mfiore 0:a44e71488e1f 152
mfiore 0:a44e71488e1f 153 logDebug("sending SMS to %s:\r\n%s", phone_number.c_str(), sms_str.c_str());
mfiore 0:a44e71488e1f 154 Code ret = radio->sendSMS(phone_number, sms_str);
mfiore 0:a44e71488e1f 155 if (ret != MTS_SUCCESS)
mfiore 0:a44e71488e1f 156 logError("sending SMS failed");
mfiore 0:a44e71488e1f 157 }
mfiore 0:a44e71488e1f 158 }
mfiore 0:a44e71488e1f 159
mfiore 4:730b61258422 160 if (post_timer.read_ms() > post_interval_ms && do_cloud_post) {
mfiore 4:730b61258422 161 if (radio->connect()) {
mfiore 4:730b61258422 162 logDebug("posting sensor data");
mfiore 5:a946ef74a8c4 163
mfiore 5:a946ef74a8c4 164 HTTPClient http;
mfiore 5:a946ef74a8c4 165 MbedJSONValue http_json_data;
mfiore 5:a946ef74a8c4 166 std::string http_json_str;
mfiore 5:a946ef74a8c4 167 std::string m2x_header = "X-M2X-KEY: " + m2x_api_key + "\r\n";
mfiore 5:a946ef74a8c4 168 int ret;
mfiore 5:a946ef74a8c4 169 char http_response_buf[256];
mfiore 5:a946ef74a8c4 170 HTTPText http_response(http_response_buf, sizeof(http_response_buf));
mfiore 5:a946ef74a8c4 171
mfiore 6:d6cf1bf4130e 172 // moisture is a stream ID for my device in M2X
mfiore 6:d6cf1bf4130e 173 // modify this to match your streams or give your stream the same name
mfiore 5:a946ef74a8c4 174 http_json_data["values"]["moisture"] = moisture_percent;
mfiore 5:a946ef74a8c4 175 http_json_str = http_json_data.serialize();
mfiore 5:a946ef74a8c4 176
mfiore 5:a946ef74a8c4 177 // add extra header with M2X API key
mfiore 5:a946ef74a8c4 178 http.setHeader(m2x_header.c_str());
mfiore 5:a946ef74a8c4 179
mfiore 5:a946ef74a8c4 180 HTTPJson http_json((char*) http_json_str.c_str());
mfiore 5:a946ef74a8c4 181 ret = http.post(url.c_str(), http_json, &http_response);
mfiore 5:a946ef74a8c4 182 if (ret != HTTP_OK)
mfiore 5:a946ef74a8c4 183 logError("posting data to cloud failed: [%d][%s]", ret, http_response_buf);
mfiore 5:a946ef74a8c4 184 else
mfiore 5:a946ef74a8c4 185 logDebug("post result [%d][%s]", http.getHTTPResponseCode(), http_response_buf);
mfiore 5:a946ef74a8c4 186
mfiore 4:730b61258422 187 radio->disconnect();
mfiore 4:730b61258422 188 } else {
mfiore 4:730b61258422 189 logError("establishing PPP link failed");
mfiore 4:730b61258422 190 }
mfiore 4:730b61258422 191
mfiore 4:730b61258422 192 post_timer.reset();
mfiore 4:730b61258422 193 }
mfiore 4:730b61258422 194
mfiore 1:a049d113e250 195 wait_ms(10);
mfiore 0:a44e71488e1f 196 }
mfiore 0:a44e71488e1f 197 }
mfiore 0:a44e71488e1f 198
mfiore 1:a049d113e250 199 // init functions
mfiore 1:a049d113e250 200 bool init_mtsas() {
mfiore 1:a049d113e250 201 io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
mfiore 1:a049d113e250 202 if (! io)
mfiore 1:a049d113e250 203 return false;
mfiore 1:a049d113e250 204
mfiore 1:a049d113e250 205 io->baud(115200);
mfiore 1:a049d113e250 206 radio = CellularFactory::create(io);
mfiore 1:a049d113e250 207 if (! radio)
mfiore 1:a049d113e250 208 return false;
mfiore 1:a049d113e250 209
mfiore 1:a049d113e250 210 Code ret = radio->setApn(apn);
mfiore 1:a049d113e250 211 if (ret != MTS_SUCCESS)
mfiore 1:a049d113e250 212 return false;
mfiore 1:a049d113e250 213
mfiore 5:a946ef74a8c4 214 Transport::setTransport(radio);
mfiore 5:a946ef74a8c4 215
mfiore 1:a049d113e250 216 return true;
mfiore 1:a049d113e250 217 }
mfiore 1:a049d113e250 218
mfiore 0:a44e71488e1f 219 // Sensor data acquisition functions
mfiore 0:a44e71488e1f 220
mfiore 0:a44e71488e1f 221 void read_moisture() {
mfiore 3:f6bceb9e5e1a 222 moisture_percent = moisture_sensor * 100.0;
mfiore 0:a44e71488e1f 223 }
mfiore 0:a44e71488e1f 224
mfiore 1:a049d113e250 225 void button_irq() {
mfiore 1:a049d113e250 226 button_pressed = true;
mfiore 1:a049d113e250 227 }