salesforce HeartRate monitor sample application. This application sends periodic heart rate values into salesforce.com via the mbed SalesforceInterface API.

Dependencies:   BufferedSerial C12832 EthernetInterface GroveEarbudSensor Logger SalesforceInterface mbed-rtos mbed

Fork of df-2014-salesforce-hrm-k64f by Doug Anson

Committer:
ansond
Date:
Thu Aug 20 19:05:31 2015 +0000
Revision:
15:bbb1cf6d0b38
Parent:
10:4c526b2bd92c
updated endpoint to latest libs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:a298d18da239 1 /* Copyright C2014 ARM, MIT License
ansond 0:a298d18da239 2 *
ansond 0:a298d18da239 3 * Author: Doug Anson (doug.anson@arm.com)
ansond 0:a298d18da239 4 *
ansond 0:a298d18da239 5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:a298d18da239 6 * and associated documentation files the "Software", to deal in the Software without restriction,
ansond 0:a298d18da239 7 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:a298d18da239 8 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:a298d18da239 9 * furnished to do so, subject to the following conditions:
ansond 0:a298d18da239 10 *
ansond 0:a298d18da239 11 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:a298d18da239 12 * substantial portions of the Software.
ansond 0:a298d18da239 13 *
ansond 0:a298d18da239 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:a298d18da239 15 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:a298d18da239 16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:a298d18da239 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:a298d18da239 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:a298d18da239 19 */
ansond 0:a298d18da239 20
ansond 0:a298d18da239 21 #include "Definitions.h" // definitions including platform specifics...
ansond 10:4c526b2bd92c 22 #include "Logger.h"
ansond 0:a298d18da239 23
ansond 0:a298d18da239 24 // include salesforce.com credentials
ansond 0:a298d18da239 25 #include "sf_creds.h"
ansond 0:a298d18da239 26
ansond 0:a298d18da239 27 // our Serial port
ansond 0:a298d18da239 28 #include "BufferedSerial.h"
ansond 0:a298d18da239 29 BufferedSerial pc(USBTX, USBRX);
ansond 0:a298d18da239 30 #define LOG_CONSOLE(...) { pc.printf(__VA_ARGS__); }
ansond 0:a298d18da239 31
ansond 0:a298d18da239 32 // mbed AppBoard Shield LCD
ansond 0:a298d18da239 33 C12832 lcd(D11, D13, D12, D7, D10);
ansond 0:a298d18da239 34
ansond 6:d5a7ca880c20 35 // Earbud support
ansond 6:d5a7ca880c20 36 #include "GroveEarbudSensor.h"
ansond 15:bbb1cf6d0b38 37 InterruptIn sensor(D2);
ansond 6:d5a7ca880c20 38 GroveEarbudSensor earbud(&sensor,&pc);
ansond 0:a298d18da239 39
ansond 0:a298d18da239 40 // Ethernet
ansond 0:a298d18da239 41 #include "EthernetInterface.h"
ansond 0:a298d18da239 42 EthernetInterface ethernet;
ansond 0:a298d18da239 43
ansond 0:a298d18da239 44 // HTTP
ansond 0:a298d18da239 45 #include "HTTPClient.h"
ansond 0:a298d18da239 46 HTTPClient http;
ansond 0:a298d18da239 47
ansond 0:a298d18da239 48 // Salesforce.com Interface
ansond 0:a298d18da239 49 #include "SalesforceInterface.h"
ansond 0:a298d18da239 50
ansond 4:73f9d7560e93 51 // Sensor Lat/Long - Moscone West: 37.783588, -122.403392
ansond 4:73f9d7560e93 52 #define SENSOR_LATITUDE "37.783588"
ansond 4:73f9d7560e93 53 #define SENSOR_LONGITUDE "-122.403392"
ansond 1:a71236906eed 54
ansond 0:a298d18da239 55 // Salesforce.com Configuration/Tunables
ansond 0:a298d18da239 56 char *hrm_object_name = "HeartRate__c"; // custom object
ansond 0:a298d18da239 57 char *hrm_bpm_field_name = "bpm__c"; // heartrate field
ansond 0:a298d18da239 58 char *hrm_user_field_name = "Name"; // heartrate user
ansond 0:a298d18da239 59 char *hrm_counter_field_name = "count__c"; // heartrate counter
ansond 1:a71236906eed 60 char *hrm_latitude = "latitude__c"; // sensor latitude
ansond 1:a71236906eed 61 char *hrm_longitude = "longitude__c"; // sensor longitude
ansond 0:a298d18da239 62 char *hrm_user = "Doug Anson"; // whos heartrate is this?
ansond 0:a298d18da239 63
ansond 0:a298d18da239 64 // main loop toggle
ansond 0:a298d18da239 65 bool do_loop = true;
ansond 0:a298d18da239 66
ansond 0:a298d18da239 67 // # retries before we give up and exit
ansond 0:a298d18da239 68 int num_retries = MAX_TRIES;
ansond 0:a298d18da239 69
ansond 0:a298d18da239 70 // heartrate values and iteration counter
ansond 6:d5a7ca880c20 71 volatile int oldheartrate = HEARTRATE_OFF;
ansond 3:3a5fdfdabca3 72 volatile int iteration_counter = 1;
ansond 0:a298d18da239 73
ansond 0:a298d18da239 74 // Salesforce.com record ID
ansond 0:a298d18da239 75 DEFINE_SML_BUFFER(bpm_record_id);
ansond 0:a298d18da239 76
ansond 0:a298d18da239 77 // Create the heart rate record in Salesforce.com
ansond 10:4c526b2bd92c 78 void create_heartrate_record(Logger *logger,SalesforceInterface *sf) {
ansond 0:a298d18da239 79 // create a new record
ansond 0:a298d18da239 80 MbedJSONValue bpm_record;
ansond 6:d5a7ca880c20 81 int heartrate = (int)earbud.getHeartRate();
ansond 3:3a5fdfdabca3 82 bpm_record[hrm_bpm_field_name] = heartrate;
ansond 0:a298d18da239 83 bpm_record[hrm_user_field_name] = hrm_user;
ansond 0:a298d18da239 84 bpm_record[hrm_counter_field_name] = (int)iteration_counter;
ansond 1:a71236906eed 85 bpm_record[hrm_latitude] = SENSOR_LATITUDE;
ansond 1:a71236906eed 86 bpm_record[hrm_longitude] = SENSOR_LONGITUDE;
ansond 0:a298d18da239 87
ansond 6:d5a7ca880c20 88 logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...",APP_VERSION,iteration_counter,heartrate);
ansond 0:a298d18da239 89 logger->logConsole("Initializing BPM record: %s",bpm_record.serialize().c_str());
ansond 0:a298d18da239 90
ansond 0:a298d18da239 91 // create the BPM record in salesforce.com
ansond 0:a298d18da239 92 MbedJSONValue response = sf->createRecord(hrm_object_name,bpm_record);
ansond 0:a298d18da239 93
ansond 0:a298d18da239 94 // display the result
ansond 0:a298d18da239 95 char *result = (char *)response.serialize().c_str();
ansond 0:a298d18da239 96 if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
ansond 0:a298d18da239 97 // save off the token if we succeeded
ansond 6:d5a7ca880c20 98 logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...SUCCESS",APP_VERSION,iteration_counter,heartrate);
ansond 0:a298d18da239 99 logger->logConsole("Create: result: %s http_code = %d",result,sf->httpResponseCode());
ansond 0:a298d18da239 100 RESET_SML_BUFFER(bpm_record_id);
ansond 0:a298d18da239 101 strcpy(bpm_record_id,(char *)response["id"].get<std::string>().c_str());
ansond 0:a298d18da239 102 logger->turnLEDGreen();
ansond 6:d5a7ca880c20 103 if (heartrate > 0) oldheartrate = heartrate;
ansond 3:3a5fdfdabca3 104 ++iteration_counter;
ansond 0:a298d18da239 105 }
ansond 0:a298d18da239 106 else {
ansond 0:a298d18da239 107 // failure
ansond 6:d5a7ca880c20 108 logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...FAILED",APP_VERSION,iteration_counter,heartrate);
ansond 0:a298d18da239 109 logger->logConsole("Create: FAILED http_code=%d",sf->httpResponseCode());
ansond 0:a298d18da239 110 logger->turnLEDRed();
ansond 0:a298d18da239 111 do_loop = false;
ansond 0:a298d18da239 112 }
ansond 0:a298d18da239 113 }
ansond 0:a298d18da239 114
ansond 0:a298d18da239 115 // Update the heart rate record in Salesforce.com
ansond 10:4c526b2bd92c 116 void update_heartrate_record(Logger *logger,SalesforceInterface *sf) {
ansond 0:a298d18da239 117 logger->turnLEDOrange();
ansond 0:a298d18da239 118
ansond 3:3a5fdfdabca3 119 // get our latest heartrate
ansond 6:d5a7ca880c20 120 int heartrate = (int)earbud.getHeartRate();
ansond 0:a298d18da239 121
ansond 3:3a5fdfdabca3 122 // only update SF if we have a valid change
ansond 6:d5a7ca880c20 123 if (heartrate > 0 && heartrate != oldheartrate) {
ansond 3:3a5fdfdabca3 124 // update am existing record - assume "name" is the proper key for the record you wish to update...
ansond 3:3a5fdfdabca3 125 MbedJSONValue bpm_record;
ansond 3:3a5fdfdabca3 126 bpm_record[hrm_bpm_field_name] = heartrate;
ansond 3:3a5fdfdabca3 127 bpm_record[hrm_user_field_name] = hrm_user;
ansond 3:3a5fdfdabca3 128 bpm_record[hrm_counter_field_name] = (int)iteration_counter;
ansond 3:3a5fdfdabca3 129 bpm_record[hrm_latitude] = SENSOR_LATITUDE;
ansond 3:3a5fdfdabca3 130 bpm_record[hrm_longitude] = SENSOR_LONGITUDE;
ansond 3:3a5fdfdabca3 131
ansond 3:3a5fdfdabca3 132 // DEBUG
ansond 3:3a5fdfdabca3 133 logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...",APP_VERSION,iteration_counter,heartrate);
ansond 3:3a5fdfdabca3 134 logger->logConsole("Update: updated record: %s",bpm_record.serialize().c_str());
ansond 3:3a5fdfdabca3 135
ansond 3:3a5fdfdabca3 136 // update the BPM record in salesforce.com
ansond 3:3a5fdfdabca3 137 bool updated = sf->updateRecord(hrm_object_name,bpm_record_id,bpm_record);
ansond 3:3a5fdfdabca3 138
ansond 3:3a5fdfdabca3 139 // display the result
ansond 3:3a5fdfdabca3 140 if (updated) {
ansond 3:3a5fdfdabca3 141 // SUCCESS
ansond 3:3a5fdfdabca3 142 logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...SUCCESS",APP_VERSION,iteration_counter,heartrate);
ansond 3:3a5fdfdabca3 143 logger->logConsole("Update: successful! http_code=%d",sf->httpResponseCode());
ansond 3:3a5fdfdabca3 144 logger->turnLEDGreen();
ansond 6:d5a7ca880c20 145 if (heartrate > 0) { oldheartrate = heartrate; ++iteration_counter; }
ansond 3:3a5fdfdabca3 146 }
ansond 3:3a5fdfdabca3 147 else {
ansond 3:3a5fdfdabca3 148 if (num_retries > 0) {
ansond 3:3a5fdfdabca3 149 // retry state
ansond 3:3a5fdfdabca3 150 logger->turnLEDPurple();
ansond 3:3a5fdfdabca3 151
ansond 3:3a5fdfdabca3 152 // OAUTH token may have expired - reset and retry
ansond 3:3a5fdfdabca3 153 logger->logConsole("Retrying update (%d of %d)...",(MAX_TRIES - num_retries)+1, MAX_TRIES);
ansond 3:3a5fdfdabca3 154 if (num_retries == MAX_TRIES) --iteration_counter; // one time only in retries...
ansond 3:3a5fdfdabca3 155 --num_retries;
ansond 3:3a5fdfdabca3 156 sf->resetSalesforceToken();
ansond 3:3a5fdfdabca3 157 update_heartrate_record(logger,sf);
ansond 3:3a5fdfdabca3 158 }
ansond 3:3a5fdfdabca3 159 else {
ansond 3:3a5fdfdabca3 160 // failure
ansond 3:3a5fdfdabca3 161 logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...FAILED",APP_VERSION,iteration_counter,heartrate);
ansond 3:3a5fdfdabca3 162 logger->logConsole("Update: FAILED http_code=%d",sf->httpResponseCode());
ansond 3:3a5fdfdabca3 163 do_loop = false;
ansond 3:3a5fdfdabca3 164
ansond 3:3a5fdfdabca3 165 // give-up state
ansond 3:3a5fdfdabca3 166 logger->turnLEDRed();
ansond 3:3a5fdfdabca3 167 }
ansond 3:3a5fdfdabca3 168 }
ansond 0:a298d18da239 169 }
ansond 0:a298d18da239 170 else {
ansond 3:3a5fdfdabca3 171 logger->logConsole("Heartrate unchanged...");
ansond 3:3a5fdfdabca3 172 logger->turnLEDGreen();
ansond 0:a298d18da239 173 }
ansond 0:a298d18da239 174 }
ansond 0:a298d18da239 175
ansond 0:a298d18da239 176 // Report heart rate to Salesforce.com
ansond 10:4c526b2bd92c 177 void report_heartrate(Logger *logger,SalesforceInterface *sf) {
ansond 3:3a5fdfdabca3 178 if (iteration_counter == 1) create_heartrate_record(logger,sf);
ansond 0:a298d18da239 179 else update_heartrate_record(logger,sf);
ansond 0:a298d18da239 180 }
ansond 0:a298d18da239 181
ansond 0:a298d18da239 182 // Main Task...
ansond 0:a298d18da239 183 void mainTask(void const *v) {
ansond 0:a298d18da239 184
ansond 0:a298d18da239 185 // create our object instances
ansond 10:4c526b2bd92c 186 Logger logger(&pc,&lcd);
ansond 0:a298d18da239 187 SalesforceInterface *sf = NULL;
ansond 0:a298d18da239 188
ansond 0:a298d18da239 189 // announce
ansond 0:a298d18da239 190 logger.log("\r\n\r\nARM Salesforce HRM v%s",APP_VERSION);
ansond 0:a298d18da239 191 logger.turnLEDBlue();
ansond 0:a298d18da239 192 wait(1);
ansond 0:a298d18da239 193
ansond 0:a298d18da239 194 // initialize Ethernet
ansond 0:a298d18da239 195 logger.log("Initializing Ethernet...");
ansond 0:a298d18da239 196 ethernet.init();
ansond 0:a298d18da239 197
ansond 0:a298d18da239 198 // get a DHCP address and bring the network interface up
ansond 0:a298d18da239 199 logger.log("Getting IP Address...");
ansond 0:a298d18da239 200 logger.turnLEDYellow();
ansond 0:a298d18da239 201 if (ethernet.connect() == 0) {
ansond 0:a298d18da239 202 // log our IP address (DHCP)
ansond 0:a298d18da239 203 logger.log("IP Address: %s",ethernet.getIPAddress());
ansond 0:a298d18da239 204
ansond 0:a298d18da239 205 // allocate the Salesforce.com interface
ansond 0:a298d18da239 206 logger.logConsole("Allocating the Saleforce.com interface...");
ansond 10:4c526b2bd92c 207 sf = new SalesforceInterface(&http,&logger);
ansond 0:a298d18da239 208
ansond 0:a298d18da239 209 // set our Salesforce.com credentials
ansond 0:a298d18da239 210 logger.logConsole("Setting credentials in the Salesforce.com interface...");
ansond 0:a298d18da239 211 sf->setCredentials(username,password,client_id,client_secret);
ansond 0:a298d18da239 212
ansond 0:a298d18da239 213 // enter main loop
ansond 0:a298d18da239 214 logger.logConsole("Beginning main event loop...");
ansond 0:a298d18da239 215 while(do_loop) {
ansond 0:a298d18da239 216 report_heartrate(&logger,sf);
ansond 0:a298d18da239 217 Thread::wait(WAIT_TIME_MS);
ansond 0:a298d18da239 218 }
ansond 0:a298d18da239 219
ansond 0:a298d18da239 220 // if we fell out of the loop exit...
ansond 0:a298d18da239 221 logger.log("Application Exiting...");
ansond 0:a298d18da239 222 logger.turnLEDRed();
ansond 0:a298d18da239 223 exit(1);
ansond 0:a298d18da239 224 }
ansond 0:a298d18da239 225 else {
ansond 0:a298d18da239 226 logger.log("No Network... Exiting...");
ansond 0:a298d18da239 227 logger.turnLEDRed();
ansond 0:a298d18da239 228 exit(1);
ansond 0:a298d18da239 229 }
ansond 0:a298d18da239 230 }
ansond 0:a298d18da239 231
ansond 0:a298d18da239 232 // main entry
ansond 0:a298d18da239 233 int main() {
ansond 0:a298d18da239 234 Thread workerTask(mainTask, NULL, osPriorityNormal, STACK_SIZE);
ansond 0:a298d18da239 235 while (true) {
ansond 0:a298d18da239 236 Thread::wait(10*WAIT_TIME_MS);
ansond 0:a298d18da239 237 }
ansond 0:a298d18da239 238 }