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

Revision:
0:a298d18da239
Child:
1:a71236906eed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,288 @@
+/* Copyright C2014 ARM, MIT License
+ *
+ * Author: Doug Anson (doug.anson@arm.com)
+ *
+ * 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.
+ */
+
+ #include "Definitions.h"       // definitions including platform specifics...
+ #include "ErrorHandler.h"
+ 
+ // HRM sensor defines
+ #define HRM_OFF                           0                                  // earbud sensor is offline
+ #define HRM_MIN                           10                                 // min HRM
+ #define HRM_MAX                           250                                // max HRM
+
+ // include salesforce.com credentials
+ #include "sf_creds.h"
+ 
+ // our Serial port
+ #include "BufferedSerial.h"
+ BufferedSerial pc(USBTX, USBRX);
+ #define LOG_CONSOLE(...) { pc.printf(__VA_ARGS__); }
+ 
+ // mbed AppBoard Shield LCD
+ C12832 lcd(D11, D13, D12, D7, D10);
+ 
+ // Earbud 
+ InterruptIn earbud(D0);
+ Timer       t;
+     
+ // Ethernet
+ #include "EthernetInterface.h"
+ EthernetInterface ethernet;
+ 
+ // HTTP 
+ #include "HTTPClient.h"
+ HTTPClient http;
+ 
+ // Salesforce.com Interface
+ #include "SalesforceInterface.h"
+ 
+ // Salesforce.com Configuration/Tunables
+ char *hrm_object_name          = "HeartRate__c";            // custom object 
+ char *hrm_bpm_field_name       = "bpm__c";                  // heartrate field
+ char *hrm_user_field_name      = "Name";                    // heartrate user
+ char *hrm_counter_field_name   = "count__c";                // heartrate counter
+ char *hrm_user                 = "Doug Anson";              // whos heartrate is this?
+ 
+ // main loop toggle
+ bool do_loop                   = true;
+ 
+ // # retries before we give up and exit
+ int num_retries                = MAX_TRIES;
+  
+ // heartrate values and iteration counter
+ volatile int iteration_counter = 0;
+ volatile int oldhrmCounter     = HRM_MAX+1;
+ volatile int hrmCounter        = HRM_OFF;
+
+ // Earbud sensor tunables 
+ #define NUM_SLOTS                         11                                 // larger numbers give more fidelity but slow down the acquisition response rate
+ volatile unsigned char counter          = 0;
+ volatile unsigned long temp[NUM_SLOTS];
+ volatile unsigned long sub              = 0;
+ volatile bool data_effect               = true;
+ const int max_heartpluse_duty           = 2000;                              // Change to follow your system's request. System returns error if the duty overtrips by 2 seconds. (in MS)
+ 
+ // Salesforce.com record ID 
+ DEFINE_SML_BUFFER(bpm_record_id);                           
+
+ // initialize the array
+ void arrayInit() {
+    for(int i=0;i<(NUM_SLOTS-1);++i) temp[i]=0;
+    temp[NUM_SLOTS-1] = t.read_ms();
+ }
+
+ // summation function
+ void sum() {
+   if(data_effect) {
+      int tmp = 60 * (NUM_SLOTS-1) * 1000;
+      hrmCounter = tmp/(temp[NUM_SLOTS-1]-temp[0]);
+      LOG_CONSOLE("Heart_rate_is: %d bpm\r\n",hrmCounter);
+   }
+   data_effect=1;  //sign bit
+}
+
+ // interrupt() function for earbud
+ void interrupt() {
+    temp[counter] = t.read_ms();
+    switch(counter) {
+        case 0:
+            sub=temp[counter]-temp[NUM_SLOTS-1];
+            break;
+        default:
+            sub=temp[counter]-temp[counter-1];
+            break;
+    }
+    if(sub > max_heartpluse_duty) { //set 2 seconds as max heart pluse duty
+        data_effect=0;//sign bit
+        counter=0;
+        LOG_CONSOLE("Heart rate measure error. Restarting...\r\n");
+        arrayInit();
+        t.stop();
+        t.start();
+    }
+    if (counter == (NUM_SLOTS-1) && data_effect) {
+        counter=0;
+        sum();
+    }
+    else if(counter != (NUM_SLOTS-1) && data_effect) {
+        counter++;
+    }
+    else {
+        counter=0;
+        data_effect=1;
+    }
+ }
+
+ // Get the heartrate from the sensor
+ int get_heartrate() {
+     ++iteration_counter;
+     return hrmCounter;
+ }
+ 
+ // Create the heart rate record in Salesforce.com
+ void create_heartrate_record(ErrorHandler *logger,SalesforceInterface *sf) {
+     // create a new record
+     MbedJSONValue bpm_record;
+     bpm_record[hrm_bpm_field_name]     = (int)get_heartrate();
+     bpm_record[hrm_user_field_name]    = hrm_user;
+     bpm_record[hrm_counter_field_name] = (int)iteration_counter;
+     
+     logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...",APP_VERSION,iteration_counter,hrmCounter);
+     logger->logConsole("Initializing BPM record: %s",bpm_record.serialize().c_str());
+     
+     // create the BPM record in salesforce.com
+     MbedJSONValue response = sf->createRecord(hrm_object_name,bpm_record);
+     
+     // display the result
+     char *result = (char *)response.serialize().c_str();
+     if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
+        // save off the token if we succeeded
+        logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...SUCCESS",APP_VERSION,iteration_counter,hrmCounter);
+        logger->logConsole("Create: result: %s http_code = %d",result,sf->httpResponseCode());
+        RESET_SML_BUFFER(bpm_record_id);
+        strcpy(bpm_record_id,(char *)response["id"].get<std::string>().c_str());
+        logger->turnLEDGreen();
+     }
+     else {
+        // failure
+        logger->log("ARM Salesforce HRM v%s\r\nCreate: new bpm record(%d): %d\r\nSending...FAILED",APP_VERSION,iteration_counter,hrmCounter);
+        logger->logConsole("Create: FAILED http_code=%d",sf->httpResponseCode());
+        logger->turnLEDRed();
+        do_loop = false;
+     }
+ }
+ 
+ // Update the heart rate record in Salesforce.com
+ void update_heartrate_record(ErrorHandler *logger,SalesforceInterface *sf) {
+     logger->turnLEDOrange();
+     
+     // update am existing record - assume "name" is the proper key for the record you wish to update...
+     MbedJSONValue bpm_record;
+     int bpm = get_heartrate();
+     bpm_record[hrm_bpm_field_name]     = bpm;
+     bpm_record[hrm_user_field_name]    = hrm_user;
+     bpm_record[hrm_counter_field_name] = (int)iteration_counter;
+     
+     // DEBUG
+     logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...",APP_VERSION,iteration_counter,bpm);
+     logger->logConsole("Update: updated record: %s",bpm_record.serialize().c_str());
+     
+     // update the BPM record in salesforce.com
+     bool updated = sf->updateRecord(hrm_object_name,bpm_record_id,bpm_record);
+     
+     // display the result
+     if (updated) {
+        // SUCCESS
+        logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...SUCCESS",APP_VERSION,iteration_counter,bpm);
+        logger->logConsole("Update: successful! http_code=%d",sf->httpResponseCode());
+        logger->turnLEDGreen();
+     }
+     else {
+        if (num_retries > 0) {
+            // retry state
+            logger->turnLEDPurple();
+            
+            // OAUTH token may have expired - reset and retry
+            if (num_retries == MAX_TRIES) --iteration_counter;        // one time only in retries...
+            --num_retries;
+            sf->resetSalesforceToken();
+            update_heartrate_record(logger,sf);
+        }
+        else {
+            // failure
+            logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...FAILED",APP_VERSION,iteration_counter,bpm);
+            logger->logConsole("Update: FAILED http_code=%d",sf->httpResponseCode());
+            do_loop = false;
+            
+            // give-up state
+            logger->turnLEDRed();
+        }
+     }
+ }
+ 
+ // Report heart rate to Salesforce.com
+ void report_heartrate(ErrorHandler *logger,SalesforceInterface *sf) {
+     if (iteration_counter == 0) create_heartrate_record(logger,sf);
+     else update_heartrate_record(logger,sf);
+ }
+   
+ // Main Task...
+ void mainTask(void const *v) {
+        
+    // create our object instances 
+    ErrorHandler logger(&pc,&lcd);    
+    SalesforceInterface *sf = NULL;
+    
+    // announce
+    logger.log("\r\n\r\nARM Salesforce HRM v%s",APP_VERSION);
+    logger.turnLEDBlue();
+    wait(1);
+    
+    // initialize Ethernet
+    logger.log("Initializing Ethernet...");
+    ethernet.init();
+    
+    // get a DHCP address and bring the network interface up
+    logger.log("Getting IP Address...");
+    logger.turnLEDYellow();
+    if (ethernet.connect() == 0) {
+        // log our IP address (DHCP)
+        logger.log("IP Address: %s",ethernet.getIPAddress());
+        
+        // allocate the Salesforce.com interface
+        logger.logConsole("Allocating the Saleforce.com interface...");
+        sf = new SalesforceInterface(&logger,&http);
+        
+        // set our Salesforce.com credentials
+        logger.logConsole("Setting credentials in the Salesforce.com interface...");
+        sf->setCredentials(username,password,client_id,client_secret);
+                
+        // initialize the earbud
+        LOG_CONSOLE("Initializing Earbud...\r\n");
+        t.start();
+        arrayInit();
+        earbud.rise(&interrupt);
+        hrmCounter = HRM_OFF;
+
+        // enter main loop
+        logger.logConsole("Beginning main event loop...");
+        while(do_loop) {
+            report_heartrate(&logger,sf);
+            Thread::wait(WAIT_TIME_MS);
+        }
+        
+        // if we fell out of the loop exit...
+        logger.log("Application Exiting...");
+        logger.turnLEDRed();
+        exit(1);
+     }
+     else {
+         logger.log("No Network... Exiting...");
+         logger.turnLEDRed();
+         exit(1);
+     }     
+  }
+  
+  // main entry
+  int main() {
+     Thread workerTask(mainTask, NULL, osPriorityNormal, STACK_SIZE);
+     while (true) {
+        Thread::wait(10*WAIT_TIME_MS);
+     }
+  }
\ No newline at end of file