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

Files at this revision

API Documentation at this revision

Comitter:
ansond
Date:
Wed Sep 24 04:13:57 2014 +0000
Child:
1:a71236906eed
Commit message:
initial checkin

Changed in this revision

BufferedSerial.lib Show annotated file Show diff for this revision Revisions of this file
C12832.lib Show annotated file Show diff for this revision Revisions of this file
Definitions.h Show annotated file Show diff for this revision Revisions of this file
ErrorHandler.lib Show annotated file Show diff for this revision Revisions of this file
EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
SalesforceInterface.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
sf_creds.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/sam_grove/code/BufferedSerial/#8287e83943f0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C12832.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/chris/code/C12832/#7de323fa46fe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Definitions.h	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,54 @@
+/* Copyright C2014 ARM, MIT License
+ *
+ * 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.
+ */
+ 
+ #ifndef _DEFINITIONS_H_
+ #define _DEFINITIONS_H_
+ 
+ // mbed 
+ #include "mbed.h"
+ 
+ // Our App version
+ #define APP_VERSION               "1.0.0"
+ 
+ // Enable/Disable verbose debugging
+ #define ENABLE_DEBUG_LOGGING      false         // true - enabled, false - disabled (default)
+     
+ // maximum memory buffer chunk
+ #define MAX_BUFFER_LENGTH         2048
+  
+ // small buffer chunk
+ #define MAX_SMALL_BUFFER_LENGTH   256
+ 
+ // Blink Time
+ #define BLINK_TIME                250
+ 
+ // Max number of retries
+ #define MAX_TRIES                 3
+ 
+ // Wait Time for iterations (ms)
+ #define WAIT_TIME_MS              10000
+ 
+ // What platform we are compiling on
+ #define _K64F_PLATFORM            true
+ 
+ // K64F needs to launch the task in a thread with a large stack size...
+ #if _K64F_PLATFORM
+    #define STACK_SIZE             40000
+ #endif
+  
+ #endif // _DEFINITIONS_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ErrorHandler.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/ansond/code/ErrorHandler/#cec063a0b9a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/EthernetInterface/#5887ae6c0c2c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SalesforceInterface.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/ansond/code/SalesforceInterface/#7dc9b949bbc3
--- /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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#631c0f1008c3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/552587b429a1
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sf_creds.h	Wed Sep 24 04:13:57 2014 +0000
@@ -0,0 +1,5 @@
+ /* Tunables: Salesforce Credentials */
+ char *username      = "xxx@yyy.zzz";
+ char *password      = "password_goes_here";            // must be of the form: [password][security token]
+ char *client_id     = "customer key goes here";
+ char *client_secret = "client secret goes here";