salesforce HeartRate monitor sample application. This application sends periodic heart rate values into salesforce.com via the mbed SalesforceInterface API.
Dependencies: BufferedSerial C12832 GroveEarbudSensor EthernetInterface SalesforceInterface mbed-rtos mbed Logger
Fork of df-2014-salesforce-hrm-k64f by
main.cpp@10:4c526b2bd92c, 2014-09-26 (annotated)
- Committer:
- ansond
- Date:
- Fri Sep 26 03:43:36 2014 +0000
- Revision:
- 10:4c526b2bd92c
- Parent:
- 6:d5a7ca880c20
updates
Who changed what in which revision?
User | Revision | Line number | New 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 | 6:d5a7ca880c20 | 37 | InterruptIn sensor(D0); |
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 | } |