Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BufferedSerial C12832 EthernetInterface GroveEarbudSensor Logger SalesforceInterface mbed-rtos mbed
Fork of df-2014-salesforce-hrm-k64f by
main.cpp
- Committer:
- ansond
- Date:
- 2014-09-25
- Revision:
- 4:73f9d7560e93
- Parent:
- 3:3a5fdfdabca3
- Child:
- 6:d5a7ca880c20
File content as of revision 4:73f9d7560e93:
/* 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"
// Sensor Lat/Long - Moscone West: 37.783588, -122.403392
#define SENSOR_LATITUDE "37.783588"
#define SENSOR_LONGITUDE "-122.403392"
// 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_latitude = "latitude__c"; // sensor latitude
char *hrm_longitude = "longitude__c"; // sensor longitude
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 = 1;
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("New heartrate: %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() {
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;
int heartrate = (int)get_heartrate();
bpm_record[hrm_bpm_field_name] = heartrate;
bpm_record[hrm_user_field_name] = hrm_user;
bpm_record[hrm_counter_field_name] = (int)iteration_counter;
bpm_record[hrm_latitude] = SENSOR_LATITUDE;
bpm_record[hrm_longitude] = SENSOR_LONGITUDE;
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();
if (heartrate > 0) oldhrmCounter = heartrate;
++iteration_counter;
}
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();
// get our latest heartrate
int heartrate = get_heartrate();
// only update SF if we have a valid change
if (heartrate > 0 && heartrate != oldhrmCounter) {
// update am existing record - assume "name" is the proper key for the record you wish to update...
MbedJSONValue bpm_record;
bpm_record[hrm_bpm_field_name] = heartrate;
bpm_record[hrm_user_field_name] = hrm_user;
bpm_record[hrm_counter_field_name] = (int)iteration_counter;
bpm_record[hrm_latitude] = SENSOR_LATITUDE;
bpm_record[hrm_longitude] = SENSOR_LONGITUDE;
// DEBUG
logger->log("ARM Salesforce HRM v%s\r\nUpdate HR(%d): %d bpm\r\nSending...",APP_VERSION,iteration_counter,heartrate);
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,heartrate);
logger->logConsole("Update: successful! http_code=%d",sf->httpResponseCode());
logger->turnLEDGreen();
if (heartrate > 0) { oldhrmCounter = heartrate; ++iteration_counter; }
}
else {
if (num_retries > 0) {
// retry state
logger->turnLEDPurple();
// OAUTH token may have expired - reset and retry
logger->logConsole("Retrying update (%d of %d)...",(MAX_TRIES - num_retries)+1, MAX_TRIES);
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,heartrate);
logger->logConsole("Update: FAILED http_code=%d",sf->httpResponseCode());
do_loop = false;
// give-up state
logger->turnLEDRed();
}
}
}
else {
logger->logConsole("Heartrate unchanged...");
logger->turnLEDGreen();
}
}
// Report heart rate to Salesforce.com
void report_heartrate(ErrorHandler *logger,SalesforceInterface *sf) {
if (iteration_counter == 1) 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);
}
}
