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

main.cpp

Committer:
ansond
Date:
2014-09-24
Revision:
0:a298d18da239
Child:
1:a71236906eed

File content as of revision 0:a298d18da239:

/* 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);
     }
  }