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
Diff: main.cpp
- 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