Salesforce.com interface to directly access Salesforce.com

Dependencies:   HTTPClient-SSL MbedJSONValue

Dependents:   df-2014-salesforce-hrm-k64f

Fork of SalesforceInterface by Doug Anson

Committer:
ansond
Date:
Mon Dec 07 17:20:21 2015 +0000
Revision:
26:709a9dff666c
Parent:
22:3363752cd523
updated HTTPS library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:518b1ca956fc 1 /* Copyright C2014 ARM, MIT License
ansond 0:518b1ca956fc 2 *
ansond 9:a254fcd904be 3 * Author: Doug Anson (doug.anson@arm.com)
ansond 9:a254fcd904be 4 *
ansond 0:518b1ca956fc 5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:518b1ca956fc 6 * and associated documentation files the "Software", to deal in the Software without restriction,
ansond 0:518b1ca956fc 7 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:518b1ca956fc 8 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:518b1ca956fc 9 * furnished to do so, subject to the following conditions:
ansond 0:518b1ca956fc 10 *
ansond 0:518b1ca956fc 11 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:518b1ca956fc 12 * substantial portions of the Software.
ansond 0:518b1ca956fc 13 *
ansond 16:3d160f224084 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:518b1ca956fc 15 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:518b1ca956fc 16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:518b1ca956fc 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:518b1ca956fc 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:518b1ca956fc 19 */
ansond 0:518b1ca956fc 20
ansond 0:518b1ca956fc 21 #ifndef _SALESFORCE_INTERFACE_H_
ansond 0:518b1ca956fc 22 #define _SALESFORCE_INTERFACE_H_
ansond 0:518b1ca956fc 23
ansond 21:e5a4471a46fb 24 // Logger
ansond 21:e5a4471a46fb 25 #include "Logger.h"
ansond 0:518b1ca956fc 26
ansond 0:518b1ca956fc 27 // SSL-based HTTP support
ansond 0:518b1ca956fc 28 #include "HTTPClient.h"
ansond 0:518b1ca956fc 29
ansond 0:518b1ca956fc 30 // JSON parsing support
ansond 0:518b1ca956fc 31 #include "MbedJSONValue.h"
ansond 21:e5a4471a46fb 32
ansond 7:97ea5ef906f7 33 // convenience macros
ansond 8:47db53cd5884 34 #define DEFINE_BUFFER(x) char x[MAX_BUFFER_LENGTH+1]
ansond 8:47db53cd5884 35 #define RESET_BUFFER(x) memset(x,0,MAX_BUFFER_LENGTH+1)
ansond 8:47db53cd5884 36 #define ALLOC_BUFFER(x) DEFINE_BUFFER(x);RESET_BUFFER(x)
ansond 8:47db53cd5884 37
ansond 8:47db53cd5884 38 #define DEFINE_SML_BUFFER(x) char x[MAX_SMALL_BUFFER_LENGTH+1]
ansond 8:47db53cd5884 39 #define RESET_SML_BUFFER(x) memset(x,0,MAX_SMALL_BUFFER_LENGTH+1)
ansond 8:47db53cd5884 40 #define ALLOC_SML_BUFFER(x) DEFINE_SML_BUFFER(x);RESET_SML_BUFFER(x)
ansond 8:47db53cd5884 41
ansond 8:47db53cd5884 42 // Default salesforce API version (must be in XX.Y format and must be a string)
ansond 8:47db53cd5884 43 #define SALESFORCE_API_VERSION_LENGTH 10
ansond 8:47db53cd5884 44 #ifndef SALESFORCE_API_VERSION
ansond 8:47db53cd5884 45 #define SALESFORCE_API_VERSION "28.0"
ansond 8:47db53cd5884 46 #endif
ansond 0:518b1ca956fc 47
ansond 21:e5a4471a46fb 48 // verbose debugging within SalesforceInterface
ansond 21:e5a4471a46fb 49 #if ENABLE_DEBUG_LOGGING
ansond 21:e5a4471a46fb 50 #define DEBUG(...) { LOG_CONSOLE(__VA_ARGS__); }
ansond 21:e5a4471a46fb 51 #else
ansond 21:e5a4471a46fb 52 #define DEBUG(...) { ; }
ansond 21:e5a4471a46fb 53 #endif
ansond 21:e5a4471a46fb 54
ansond 0:518b1ca956fc 55 // HTTP Verbs
ansond 0:518b1ca956fc 56 typedef enum {
ansond 0:518b1ca956fc 57 GET,
ansond 0:518b1ca956fc 58 PUT,
ansond 0:518b1ca956fc 59 POST,
ansond 0:518b1ca956fc 60 DELETE,
ansond 0:518b1ca956fc 61 NUM_VERBS
ansond 0:518b1ca956fc 62 } HttpVerb;
ansond 0:518b1ca956fc 63
ansond 0:518b1ca956fc 64 // Supported input data types for PUT and POST (Defined by HTTPClient-SSL/data support...)
ansond 0:518b1ca956fc 65 typedef enum {
ansond 0:518b1ca956fc 66 JSON, // ContentType: application/json
ansond 0:518b1ca956fc 67 PLAIN_TEXT, // ContentType: plain/text
ansond 0:518b1ca956fc 68 FORM_MAPPED, // ContentType: application/x-www-form-urlencoded
ansond 0:518b1ca956fc 69 NUM_TYPES
ansond 0:518b1ca956fc 70 } InputDataTypes;
ansond 0:518b1ca956fc 71
ansond 7:97ea5ef906f7 72 // OAUTH structure
ansond 7:97ea5ef906f7 73 typedef struct {
ansond 7:97ea5ef906f7 74 bool valid;
ansond 7:97ea5ef906f7 75 string id;
ansond 7:97ea5ef906f7 76 string issued_at;
ansond 7:97ea5ef906f7 77 string token_type;
ansond 7:97ea5ef906f7 78 string instance_url;
ansond 7:97ea5ef906f7 79 string signature;
ansond 7:97ea5ef906f7 80 string access_token;
ansond 7:97ea5ef906f7 81 } OauthToken;
ansond 10:845ea6d00b65 82
ansond 13:3088dd4b4bef 83 /**
ansond 13:3088dd4b4bef 84 * Salesforce Interface
ansond 13:3088dd4b4bef 85 * SalesforceInterface provides a simple C++ API into the REST-based Salesforce.com APIs
ansond 13:3088dd4b4bef 86 *
ansond 13:3088dd4b4bef 87 * Example Project: http://mbed.org/users/ansond/code/df-2014-salesforce-testharness-k64f/
ansond 13:3088dd4b4bef 88 *
ansond 13:3088dd4b4bef 89 * @code
ansond 16:3d160f224084 90
ansond 16:3d160f224084 91 #include "Definitions.h" // definitions including platform specifics...
ansond 21:e5a4471a46fb 92 #include "Logger.h"
ansond 16:3d160f224084 93
ansond 16:3d160f224084 94 // include salesforce.com credentials
ansond 16:3d160f224084 95 #include "sf_creds.h"
ansond 16:3d160f224084 96
ansond 16:3d160f224084 97 // our Serial port
ansond 16:3d160f224084 98 #include "BufferedSerial.h"
ansond 16:3d160f224084 99 BufferedSerial pc(USBTX, USBRX);
ansond 16:3d160f224084 100
ansond 16:3d160f224084 101 // Ethernet
ansond 16:3d160f224084 102 #include "EthernetInterface.h"
ansond 16:3d160f224084 103 EthernetInterface ethernet;
ansond 16:3d160f224084 104
ansond 16:3d160f224084 105 // HTTP
ansond 16:3d160f224084 106 #include "HTTPClient.h"
ansond 16:3d160f224084 107 HTTPClient http;
ansond 16:3d160f224084 108
ansond 16:3d160f224084 109 // Salesforce.com Interface
ansond 16:3d160f224084 110 #include "SalesforceInterface.h"
ansond 16:3d160f224084 111
ansond 16:3d160f224084 112 // test case persistence
ansond 16:3d160f224084 113 char *object_name = NULL;
ansond 16:3d160f224084 114 char *account_name = NULL;
ansond 16:3d160f224084 115 char *updated_account_name = NULL;
ansond 16:3d160f224084 116 char *external_id_field_name = NULL;
ansond 16:3d160f224084 117 char *external_id_field_value = NULL;
ansond 16:3d160f224084 118 DEFINE_SML_BUFFER(record_id);
ansond 16:3d160f224084 119
ansond 16:3d160f224084 120 // *************** Test Cases ************************
ansond 16:3d160f224084 121
ansond 21:e5a4471a46fb 122 void Test_getSalesforceToken(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 123 logger->log("\r\n\r\nGetting Salesforce Token...");
ansond 16:3d160f224084 124 logger->turnLEDPurple();
ansond 16:3d160f224084 125
ansond 16:3d160f224084 126 // get the salesforce token
ansond 16:3d160f224084 127 char *id = sf->getSalesforceToken();
ansond 16:3d160f224084 128 if (id != NULL && strlen(id) > 0)
ansond 16:3d160f224084 129 logger->log("Saleforce token: %s",id);
ansond 16:3d160f224084 130 else
ansond 16:3d160f224084 131 logger->log("Unable to get Saleforce token");
ansond 16:3d160f224084 132 logger->turnLEDGreen();
ansond 16:3d160f224084 133 }
ansond 16:3d160f224084 134
ansond 21:e5a4471a46fb 135 void Test_query(Logger *logger,SalesforceInterface *sf,char *query_str) {
ansond 16:3d160f224084 136 logger->log("\r\n\r\nExecuting test query: %s",query_str);
ansond 16:3d160f224084 137 logger->turnLEDPurple();
ansond 16:3d160f224084 138 if (query_str != NULL && strlen(query_str) > 0) {
ansond 16:3d160f224084 139 ALLOC_BUFFER(response);
ansond 16:3d160f224084 140 char *answer = sf->query(query_str,response,MAX_BUFFER_LENGTH);
ansond 16:3d160f224084 141 if (answer != NULL) logger->log("query result: %s",answer);
ansond 16:3d160f224084 142 else logger->log("query - NULL result");
ansond 16:3d160f224084 143 }
ansond 16:3d160f224084 144 else {
ansond 16:3d160f224084 145 logger->log("Unable to perform query as we do not have our salesforce token");
ansond 16:3d160f224084 146 }
ansond 16:3d160f224084 147 logger->turnLEDGreen();
ansond 16:3d160f224084 148 }
ansond 16:3d160f224084 149
ansond 21:e5a4471a46fb 150 void Test_create(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 151 logger->log("\r\n\r\nExecuting create()");
ansond 16:3d160f224084 152 logger->turnLEDPurple();
ansond 16:3d160f224084 153
ansond 16:3d160f224084 154 // create a new record
ansond 16:3d160f224084 155 MbedJSONValue new_record;
ansond 16:3d160f224084 156 new_record["name"] = account_name;
ansond 16:3d160f224084 157
ansond 16:3d160f224084 158 // DEBUG
ansond 16:3d160f224084 159 logger->log("Create: new record: %s",new_record.serialize().c_str());
ansond 16:3d160f224084 160
ansond 16:3d160f224084 161 // create...
ansond 16:3d160f224084 162 MbedJSONValue response = sf->createRecord(object_name,new_record);
ansond 16:3d160f224084 163
ansond 16:3d160f224084 164 // display the result
ansond 16:3d160f224084 165 char *result = (char *)response.serialize().c_str();
ansond 16:3d160f224084 166 if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
ansond 16:3d160f224084 167 // save off the token if we succeeded
ansond 16:3d160f224084 168 logger->log("Create: result: %s",result);
ansond 16:3d160f224084 169 logger->log("Create: http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 170 RESET_SML_BUFFER(record_id);
ansond 16:3d160f224084 171 strcpy(record_id,(char *)response["id"].get<std::string>().c_str());
ansond 16:3d160f224084 172 }
ansond 16:3d160f224084 173 else {
ansond 16:3d160f224084 174 // failure
ansond 16:3d160f224084 175 logger->log("Create: FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 176 }
ansond 16:3d160f224084 177 logger->turnLEDGreen();
ansond 16:3d160f224084 178 }
ansond 16:3d160f224084 179
ansond 21:e5a4471a46fb 180 void Test_read(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 181 logger->log("\r\n\r\nExecuting read()");
ansond 16:3d160f224084 182 logger->turnLEDPurple();
ansond 16:3d160f224084 183
ansond 16:3d160f224084 184 // DEBUG
ansond 16:3d160f224084 185 logger->log("Read: reading: %s from %s",record_id,object_name);
ansond 16:3d160f224084 186
ansond 16:3d160f224084 187 // read...
ansond 16:3d160f224084 188 MbedJSONValue response = sf->readRecord(object_name,record_id);
ansond 16:3d160f224084 189
ansond 16:3d160f224084 190 // display the result
ansond 16:3d160f224084 191 char *result = (char *)response.serialize().c_str();
ansond 16:3d160f224084 192 if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
ansond 16:3d160f224084 193 // save off the token if we succeeded
ansond 16:3d160f224084 194 logger->log("Read: result: %s",result);
ansond 16:3d160f224084 195 logger->log("Read: http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 196 }
ansond 16:3d160f224084 197 else {
ansond 16:3d160f224084 198 // failure
ansond 16:3d160f224084 199 logger->log("Read: FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 200 }
ansond 16:3d160f224084 201
ansond 16:3d160f224084 202 logger->turnLEDGreen();
ansond 16:3d160f224084 203 }
ansond 16:3d160f224084 204
ansond 21:e5a4471a46fb 205 void Test_create_external_id(Logger *logger,SalesforceInterface *sf) {
ansond 17:6c774354b599 206 logger->log("\r\n\r\nExecuting create(ExternalID)");
ansond 17:6c774354b599 207 logger->turnLEDPurple();
ansond 17:6c774354b599 208
ansond 17:6c774354b599 209 // create a new record
ansond 17:6c774354b599 210 MbedJSONValue new_record;
ansond 17:6c774354b599 211 new_record[external_id_field_name] = external_id_field_value;
ansond 17:6c774354b599 212
ansond 17:6c774354b599 213 // DEBUG
ansond 17:6c774354b599 214 logger->log("create(ExternalID): new record: %s",new_record.serialize().c_str());
ansond 17:6c774354b599 215
ansond 17:6c774354b599 216 // create...
ansond 17:6c774354b599 217 MbedJSONValue response = sf->createRecord(object_name,new_record);
ansond 17:6c774354b599 218
ansond 17:6c774354b599 219 // display the result
ansond 17:6c774354b599 220 char *result = (char *)response.serialize().c_str();
ansond 17:6c774354b599 221 if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
ansond 17:6c774354b599 222 // save off the token if we succeeded
ansond 17:6c774354b599 223 logger->log("create(ExternalID): result: %s",result);
ansond 17:6c774354b599 224 logger->log("create(ExternalID): http_code=%d",sf->httpResponseCode());
ansond 17:6c774354b599 225 RESET_SML_BUFFER(record_id);
ansond 17:6c774354b599 226 strcpy(record_id,(char *)response["id"].get<std::string>().c_str());
ansond 17:6c774354b599 227 }
ansond 17:6c774354b599 228 else {
ansond 17:6c774354b599 229 // failure
ansond 17:6c774354b599 230 logger->log("create(ExternalID): FAILED http_code=%d",sf->httpResponseCode());
ansond 17:6c774354b599 231 }
ansond 17:6c774354b599 232 logger->turnLEDGreen();
ansond 17:6c774354b599 233 }
ansond 17:6c774354b599 234
ansond 21:e5a4471a46fb 235 void Test_read_by_external_id_and_value(Logger *logger,SalesforceInterface *sf) {
ansond 17:6c774354b599 236 logger->log("\r\n\r\nExecuting read(externalID)...");
ansond 16:3d160f224084 237 logger->turnLEDPurple();
ansond 16:3d160f224084 238
ansond 16:3d160f224084 239 // DEBUG
ansond 17:6c774354b599 240 logger->log("read(externalID): reading: %s from %s with value %s",object_name,external_id_field_name,external_id_field_value);
ansond 16:3d160f224084 241
ansond 16:3d160f224084 242 // read (external ID)...
ansond 16:3d160f224084 243 MbedJSONValue response = sf->readRecord(object_name,external_id_field_name,external_id_field_value);
ansond 16:3d160f224084 244
ansond 16:3d160f224084 245 // display the result
ansond 16:3d160f224084 246 char *result = (char *)response.serialize().c_str();
ansond 16:3d160f224084 247 if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) {
ansond 16:3d160f224084 248 // save off the token if we succeeded
ansond 17:6c774354b599 249 logger->log("read(externalID): result: %s",result);
ansond 17:6c774354b599 250 logger->log("read(externalID): http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 251 }
ansond 16:3d160f224084 252 else {
ansond 16:3d160f224084 253 // failure
ansond 17:6c774354b599 254 logger->log("read(externalID): FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 255 }
ansond 16:3d160f224084 256
ansond 16:3d160f224084 257 logger->turnLEDGreen();
ansond 16:3d160f224084 258 }
ansond 16:3d160f224084 259
ansond 21:e5a4471a46fb 260 void Test_update(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 261 logger->log("\r\n\r\nExecuting update()");
ansond 16:3d160f224084 262 logger->turnLEDPurple();
ansond 16:3d160f224084 263
ansond 16:3d160f224084 264 // update am existing record - assume "name" is the proper key for the record you wish to update...
ansond 16:3d160f224084 265 MbedJSONValue changed_record;
ansond 16:3d160f224084 266 changed_record["name"] = updated_account_name;
ansond 16:3d160f224084 267
ansond 16:3d160f224084 268 // DEBUG
ansond 16:3d160f224084 269 logger->log("Update: updated record: %s",changed_record.serialize().c_str());
ansond 16:3d160f224084 270
ansond 16:3d160f224084 271 // update...
ansond 16:3d160f224084 272 bool updated = sf->updateRecord(object_name,record_id,changed_record);
ansond 16:3d160f224084 273
ansond 16:3d160f224084 274 // display the result
ansond 16:3d160f224084 275 if (updated) {
ansond 16:3d160f224084 276 // SUCCESS
ansond 16:3d160f224084 277 logger->log("Update: successful! http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 278 }
ansond 16:3d160f224084 279 else {
ansond 16:3d160f224084 280 // failure
ansond 16:3d160f224084 281 logger->log("Update: FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 282 }
ansond 16:3d160f224084 283 logger->turnLEDGreen();
ansond 16:3d160f224084 284 }
ansond 16:3d160f224084 285
ansond 21:e5a4471a46fb 286 void Test_upsert_external_id(Logger *logger,SalesforceInterface *sf) {
ansond 17:6c774354b599 287 logger->log("\r\n\r\nExecuting upsert(ExternalID)");
ansond 16:3d160f224084 288 logger->turnLEDPurple();
ansond 16:3d160f224084 289
ansond 16:3d160f224084 290 // update am existing record - assume "name" is the proper key for the record you wish to update...
ansond 16:3d160f224084 291 MbedJSONValue changed_record;
ansond 16:3d160f224084 292 changed_record["name"] = updated_account_name;
ansond 16:3d160f224084 293
ansond 16:3d160f224084 294 // DEBUG
ansond 17:6c774354b599 295 logger->log("upsert(ExternalID): upserted record: %s",changed_record.serialize().c_str());
ansond 16:3d160f224084 296
ansond 16:3d160f224084 297 // Upsert...
ansond 16:3d160f224084 298 bool updated = sf->upsertRecord(object_name,external_id_field_name,external_id_field_value,changed_record);
ansond 16:3d160f224084 299
ansond 16:3d160f224084 300 // display the result
ansond 16:3d160f224084 301 if (updated) {
ansond 16:3d160f224084 302 // SUCCESS
ansond 17:6c774354b599 303 logger->log("upsert(ExternalID): successful! http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 304 }
ansond 16:3d160f224084 305 else {
ansond 16:3d160f224084 306 // failure
ansond 17:6c774354b599 307 logger->log("upsert(ExternalID): FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 308 }
ansond 16:3d160f224084 309 logger->turnLEDGreen();
ansond 16:3d160f224084 310 }
ansond 16:3d160f224084 311
ansond 21:e5a4471a46fb 312 void Test_delete(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 313 logger->log("\r\n\r\nExecuting delete()");
ansond 16:3d160f224084 314 logger->turnLEDPurple();
ansond 16:3d160f224084 315
ansond 16:3d160f224084 316 // DEBUG
ansond 16:3d160f224084 317 logger->log("Delete: deleting: %s from %s",record_id,object_name);
ansond 16:3d160f224084 318
ansond 16:3d160f224084 319 // delete...
ansond 16:3d160f224084 320 bool deleted = sf->deleteRecord(object_name,record_id);
ansond 16:3d160f224084 321
ansond 16:3d160f224084 322 // display the result
ansond 16:3d160f224084 323 if (deleted) {
ansond 16:3d160f224084 324 // SUCCESS
ansond 16:3d160f224084 325 logger->log("Delete: successful! http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 326 }
ansond 16:3d160f224084 327 else {
ansond 16:3d160f224084 328 // failure
ansond 16:3d160f224084 329 logger->log("Delete: FAILED http_code=%d",sf->httpResponseCode());
ansond 16:3d160f224084 330 }
ansond 16:3d160f224084 331
ansond 16:3d160f224084 332 logger->turnLEDGreen();
ansond 16:3d160f224084 333 }
ansond 16:3d160f224084 334
ansond 21:e5a4471a46fb 335 void Test_reset_auth(Logger *logger,SalesforceInterface *sf) {
ansond 16:3d160f224084 336 logger->log("\r\n\r\nForcing API to reset OAUTH token and Salesforce Token...");
ansond 16:3d160f224084 337 logger->turnLEDPurple();
ansond 16:3d160f224084 338 sf->resetSalesforceToken();
ansond 16:3d160f224084 339 logger->turnLEDGreen();
ansond 16:3d160f224084 340 }
ansond 16:3d160f224084 341
ansond 16:3d160f224084 342 // *************** Test Cases ************************
ansond 16:3d160f224084 343
ansond 16:3d160f224084 344 // Main Task...
ansond 16:3d160f224084 345 void mainTask(void const *v) {
ansond 16:3d160f224084 346
ansond 16:3d160f224084 347 // create our object instances
ansond 21:e5a4471a46fb 348 Logger logger(&pc,NULL);
ansond 16:3d160f224084 349 SalesforceInterface *sf = NULL;
ansond 16:3d160f224084 350
ansond 16:3d160f224084 351 // announce
ansond 16:3d160f224084 352 logger.log("\r\n\r\nARM Salesforce Interface Testharness v%s",APP_VERSION);
ansond 16:3d160f224084 353 logger.turnLEDBlue();
ansond 16:3d160f224084 354
ansond 16:3d160f224084 355 // initialize Ethernet
ansond 16:3d160f224084 356 logger.log("Initializing Ethernet...");
ansond 16:3d160f224084 357 ethernet.init();
ansond 16:3d160f224084 358
ansond 16:3d160f224084 359 // get a DHCP address and bring the network interface up
ansond 16:3d160f224084 360 logger.log("Getting IP Address...");
ansond 16:3d160f224084 361 logger.turnLEDOrange();
ansond 16:3d160f224084 362 if (ethernet.connect() == 0) {
ansond 16:3d160f224084 363 // log our IP address (DHCP)
ansond 16:3d160f224084 364 logger.log("IP Address: %s",ethernet.getIPAddress());
ansond 16:3d160f224084 365
ansond 16:3d160f224084 366 // allocate the Salesforce.com interface
ansond 16:3d160f224084 367 logger.log("Allocating Saleforce.com interface...");
ansond 21:e5a4471a46fb 368 sf = new SalesforceInterface(&http,&logger);
ansond 16:3d160f224084 369
ansond 16:3d160f224084 370 // set our Salesforce.com credentials
ansond 16:3d160f224084 371 sf->setCredentials(username,password,client_id,client_secret);
ansond 16:3d160f224084 372
ansond 16:3d160f224084 373 // *************** BEGIN TEST CASES *****************
ansond 16:3d160f224084 374
ansond 16:3d160f224084 375 // configuration for the test cases
ansond 16:3d160f224084 376 object_name = "Account"; // use the account object
ansond 16:3d160f224084 377 account_name = "ARM"; // add this record (name)
ansond 16:3d160f224084 378 updated_account_name = "ARM Holdings"; // update the existing record's name to this
ansond 17:6c774354b599 379 external_id_field_name = "Device__c"; // External ID field name
ansond 16:3d160f224084 380 external_id_field_value = "ABC123"; // External ID field value
ansond 16:3d160f224084 381 RESET_SML_BUFFER(record_id); // buffer for the record's token
ansond 16:3d160f224084 382
ansond 16:3d160f224084 383 // Perform a Create
ansond 16:3d160f224084 384 Test_create(&logger,sf);
ansond 16:3d160f224084 385
ansond 16:3d160f224084 386 // Perform a Read
ansond 16:3d160f224084 387 Test_read(&logger,sf);
ansond 16:3d160f224084 388
ansond 16:3d160f224084 389 // Perform a Query
ansond 16:3d160f224084 390 Test_query(&logger,sf,"SELECT Id,Name FROM Account LIMIT 5");
ansond 16:3d160f224084 391
ansond 16:3d160f224084 392 // Perform an Update
ansond 16:3d160f224084 393 Test_update(&logger,sf);
ansond 16:3d160f224084 394
ansond 16:3d160f224084 395 // Perform a second Read to visually confirm the update above...
ansond 16:3d160f224084 396 Test_read(&logger,sf);
ansond 16:3d160f224084 397
ansond 17:6c774354b599 398 // Perform a Create (External ID)
ansond 17:6c774354b599 399 Test_create_external_id(&logger,sf);
ansond 17:6c774354b599 400
ansond 16:3d160f224084 401 // Perform an Upsert
ansond 17:6c774354b599 402 Test_upsert_external_id(&logger,sf);
ansond 16:3d160f224084 403
ansond 16:3d160f224084 404 // Perform a read of the external ID'ed specified by a given value
ansond 16:3d160f224084 405 Test_read_by_external_id_and_value(&logger,sf);
ansond 16:3d160f224084 406
ansond 16:3d160f224084 407 // force the API to re-acquire the OAUTH token and Salesforce Token
ansond 16:3d160f224084 408 Test_reset_auth(&logger,sf);
ansond 16:3d160f224084 409
ansond 16:3d160f224084 410 // Perform a Read (should re-acquire the OAUTH token and Salesforce Token)
ansond 16:3d160f224084 411 Test_read(&logger,sf);
ansond 16:3d160f224084 412
ansond 16:3d160f224084 413 // Perform a Delete
ansond 16:3d160f224084 414 Test_delete(&logger,sf);
ansond 16:3d160f224084 415
ansond 16:3d160f224084 416 // reset the record token buffer
ansond 16:3d160f224084 417 // RESET_SML_BUFFER(record_id);
ansond 16:3d160f224084 418
ansond 16:3d160f224084 419 // Perform a Read - should error out
ansond 16:3d160f224084 420 Test_read(&logger,sf);
ansond 16:3d160f224084 421
ansond 16:3d160f224084 422 // reset the record token buffer
ansond 16:3d160f224084 423 RESET_SML_BUFFER(record_id);
ansond 16:3d160f224084 424
ansond 16:3d160f224084 425 // *************** BEGIN TEST CASES *****************
ansond 16:3d160f224084 426
ansond 16:3d160f224084 427 // entering main loop
ansond 16:3d160f224084 428 logger.log("All tests complete...\r\nExiting...");
ansond 16:3d160f224084 429 logger.turnLEDBlue();
ansond 16:3d160f224084 430 exit(0);
ansond 16:3d160f224084 431 }
ansond 16:3d160f224084 432 else {
ansond 16:3d160f224084 433 logger.log("No Network... Exiting...");
ansond 16:3d160f224084 434 logger.turnLEDRed();
ansond 16:3d160f224084 435 exit(1);
ansond 16:3d160f224084 436 }
ansond 16:3d160f224084 437 }
ansond 16:3d160f224084 438
ansond 16:3d160f224084 439 // main entry
ansond 16:3d160f224084 440 int main() {
ansond 16:3d160f224084 441 Thread workerTask(mainTask, NULL, osPriorityNormal, STACK_SIZE);
ansond 16:3d160f224084 442 while (true) {
ansond 16:3d160f224084 443 Thread::wait(10*WAIT_TIME_MS);
ansond 16:3d160f224084 444 }
ansond 16:3d160f224084 445 }
ansond 17:6c774354b599 446
ansond 13:3088dd4b4bef 447 * @endcode
ansond 13:3088dd4b4bef 448 *
ansond 10:845ea6d00b65 449 */
ansond 0:518b1ca956fc 450 class SalesforceInterface {
ansond 0:518b1ca956fc 451 private:
ansond 21:e5a4471a46fb 452 Logger *m_logger;
ansond 21:e5a4471a46fb 453 bool m_logger_internal;
ansond 0:518b1ca956fc 454 HTTPClient *m_http;
ansond 0:518b1ca956fc 455 char *m_username;
ansond 0:518b1ca956fc 456 char *m_password;
ansond 0:518b1ca956fc 457 char *m_client_id;
ansond 0:518b1ca956fc 458 char *m_client_secret;
ansond 0:518b1ca956fc 459 bool m_have_creds;
ansond 7:97ea5ef906f7 460 OauthToken m_oauth_token;
ansond 7:97ea5ef906f7 461 HTTPResult m_http_status;
ansond 7:97ea5ef906f7 462 int m_http_response_code;
ansond 7:97ea5ef906f7 463 char m_http_redirection_url[MAX_BUFFER_LENGTH+1];
ansond 8:47db53cd5884 464 char m_salesforce_id[MAX_BUFFER_LENGTH+1];
ansond 8:47db53cd5884 465 char m_salesforce_api[SALESFORCE_API_VERSION_LENGTH];
ansond 18:7dc9b949bbc3 466 char m_error_buffer[MAX_SMALL_BUFFER_LENGTH+1];
ansond 0:518b1ca956fc 467
ansond 0:518b1ca956fc 468 public:
ansond 10:845ea6d00b65 469 /**
ansond 10:845ea6d00b65 470 Default constructor
ansond 10:845ea6d00b65 471 @param http HTTPClient instance
ansond 21:e5a4471a46fb 472 @param pc optional RawSerial for debugging output. If NULL, there will be no debugging output
ansond 10:845ea6d00b65 473 */
ansond 21:e5a4471a46fb 474 SalesforceInterface(HTTPClient *http,RawSerial *pc = NULL);
ansond 21:e5a4471a46fb 475
ansond 21:e5a4471a46fb 476 /**
ansond 21:e5a4471a46fb 477 Alternative constructor
ansond 21:e5a4471a46fb 478 @param http HTTPClient instance
ansond 21:e5a4471a46fb 479 @param logger optional Logger instance (See Logger for more info). If NULL, there will be no debugging output
ansond 21:e5a4471a46fb 480 */
ansond 21:e5a4471a46fb 481 SalesforceInterface(HTTPClient *http,Logger *logger = NULL);
ansond 10:845ea6d00b65 482
ansond 10:845ea6d00b65 483 /**
ansond 10:845ea6d00b65 484 Default destructor
ansond 10:845ea6d00b65 485 */
ansond 0:518b1ca956fc 486 virtual ~SalesforceInterface();
ansond 0:518b1ca956fc 487
ansond 10:845ea6d00b65 488 /**
ansond 10:845ea6d00b65 489 Establish salesforce.com credentials
ansond 10:845ea6d00b65 490 @param username salesforce.com account user name
ansond 12:0e7290e093df 491 @param password salesforce.com account password. The password must be of the form [password][security token]
ansond 10:845ea6d00b65 492 @param client_id salesforce.com connected application "customer key" value
ansond 12:0e7290e093df 493 @param client_secret salesforce.com connected application client secret value
ansond 10:845ea6d00b65 494 */
ansond 0:518b1ca956fc 495 void setCredentials(char *username,char *password,char *client_id,char *client_secret);
ansond 0:518b1ca956fc 496
ansond 10:845ea6d00b65 497 /**
ansond 15:89044c68ad36 498 Get our salesforce.com token
ansond 15:89044c68ad36 499 @param fetch boolean that will direct the interface to fetch the token if not already done (default = true)
ansond 15:89044c68ad36 500 @return our salesforce token in JSON format or NULL if in error
ansond 10:845ea6d00b65 501 */
ansond 14:3c8d11b48814 502 char *getSalesforceToken(bool fetch = true);
ansond 9:a254fcd904be 503
ansond 10:845ea6d00b65 504 /**
ansond 15:89044c68ad36 505 Force the interface to re-acquire the OAUTH token and salesforce token
ansond 10:845ea6d00b65 506 */
ansond 14:3c8d11b48814 507 void resetSalesforceToken();
ansond 8:47db53cd5884 508
ansond 10:845ea6d00b65 509 /**
ansond 10:845ea6d00b65 510 Set our salesforce.com API version
ansond 10:845ea6d00b65 511 @param version integer value (positive)
ansond 10:845ea6d00b65 512 */
ansond 8:47db53cd5884 513 void setSalesforceAPIVersion(int version);
ansond 10:845ea6d00b65 514
ansond 10:845ea6d00b65 515 /**
ansond 10:845ea6d00b65 516 Set our salesforce.com API version
ansond 10:845ea6d00b65 517 @param version string value (format "X.Y")
ansond 10:845ea6d00b65 518 */
ansond 8:47db53cd5884 519 void setSalesforceAPIVersion(char *version);
ansond 10:845ea6d00b65 520
ansond 10:845ea6d00b65 521 /**
ansond 10:845ea6d00b65 522 Get our salesforce.com API version
ansond 10:845ea6d00b65 523 @return string containing our salesforce.com API version or NULL if in error
ansond 10:845ea6d00b65 524 */
ansond 8:47db53cd5884 525 char *getSalesforceAPIVersion();
ansond 8:47db53cd5884 526
ansond 10:845ea6d00b65 527 /**
ansond 14:3c8d11b48814 528 Salesforce.com API SOQL QUERY method to invoke ad-hoc SOQL queries into salesforce.com
ansond 14:3c8d11b48814 529 @param query_str character string with the SOQL query to invoke
ansond 10:845ea6d00b65 530 @param output_buffer allocated result buffer to use
ansond 10:845ea6d00b65 531 @param output_buffer_length allocated result buffer length
ansond 14:3c8d11b48814 532 @return result of the SOQL query in JSON format or NULL if in error
ansond 10:845ea6d00b65 533 */
ansond 8:47db53cd5884 534 char *query(char *query_str,char *output_buffer,int output_buffer_length);
ansond 9:a254fcd904be 535
ansond 10:845ea6d00b65 536 /**
ansond 14:3c8d11b48814 537 Salesforce.com API record creation method to create a new record within a salesforce.com object
ansond 14:3c8d11b48814 538 @param object_name name of the salesforce.com object to create the record in (i.e. "Account")
ansond 14:3c8d11b48814 539 @param record MbedJSONValue json structure that the new record will be comprised with
ansond 10:845ea6d00b65 540 @return MbedJSONValue structure with the results of the creation operation in JSON format
ansond 10:845ea6d00b65 541 */
ansond 14:3c8d11b48814 542 MbedJSONValue createRecord(char *object_name,MbedJSONValue &record);
ansond 9:a254fcd904be 543
ansond 10:845ea6d00b65 544 /**
ansond 14:3c8d11b48814 545 Salesforce.com API record read method to read a record within a salesforce.com object
ansond 16:3d160f224084 546 @param object_name name of the salesforce.com object to read the record in (i.e. "Account")
ansond 16:3d160f224084 547 @param record_id salesforce.com id of the record instance to read
ansond 16:3d160f224084 548 @param record_value salesforce.com id value of the record instance to read (for external ID usage - default is NULL for non-external IDs)
ansond 10:845ea6d00b65 549 @return MbedJSONValue structure with the results of the read operation in JSON format
ansond 10:845ea6d00b65 550 */
ansond 16:3d160f224084 551 MbedJSONValue readRecord(char *object_name,char *record_id,char *record_value = NULL);
ansond 9:a254fcd904be 552
ansond 10:845ea6d00b65 553 /**
ansond 14:3c8d11b48814 554 Salesforce.com API record update method to update a record within a salesforce.com object
ansond 16:3d160f224084 555 @param object_name name of the salesforce.com object to update the record in (i.e. "Account")
ansond 16:3d160f224084 556 @param record_id salesforce.com id of the record instance to read
ansond 14:3c8d11b48814 557 @param record MbedJSONValue instance with updated data for the record
ansond 10:845ea6d00b65 558 @return true - success, false - failure
ansond 10:845ea6d00b65 559 */
ansond 14:3c8d11b48814 560 bool updateRecord(char *object_name,char *record_id,MbedJSONValue &record);
ansond 9:a254fcd904be 561
ansond 10:845ea6d00b65 562 /**
ansond 16:3d160f224084 563 Salesforce.com API record upsert (update/insert) method to update a record within a salesforce.com object for External IDs
ansond 16:3d160f224084 564 @param object_name name of the salesforce.com External object to upsert the record in (i.e. "FooBar_c")
ansond 16:3d160f224084 565 @param external_id_field_name salesforce.com id of the External record instance to upsert
ansond 16:3d160f224084 566 @param external_id_field_value salesforce.com id value of the External record instance to upsert
ansond 16:3d160f224084 567 @param record MbedJSONValue instance with updated data for the record
ansond 16:3d160f224084 568 @return true - success, false - failure
ansond 16:3d160f224084 569 */
ansond 16:3d160f224084 570 bool upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,MbedJSONValue &record);
ansond 16:3d160f224084 571
ansond 16:3d160f224084 572 /**
ansond 14:3c8d11b48814 573 Salesforce.com API record delete method to delete a record within a salesforce.com object
ansond 16:3d160f224084 574 @param object_name name of the salesforce.com object to delete the record in (i.e. "Account")
ansond 16:3d160f224084 575 @param record_id salesforce.com id of the record instance to delete
ansond 10:845ea6d00b65 576 @return true - success, false - failure
ansond 10:845ea6d00b65 577 */
ansond 14:3c8d11b48814 578 bool deleteRecord(char *object_name,char *record_id);
ansond 9:a254fcd904be 579
ansond 10:845ea6d00b65 580 /**
ansond 10:845ea6d00b65 581 Salesforce.com API invocation HTTP response code to aid in debugging error conditions
ansond 10:845ea6d00b65 582 @return http response code
ansond 10:845ea6d00b65 583 */
ansond 9:a254fcd904be 584 // HTTP Error code access
ansond 9:a254fcd904be 585 int httpResponseCode();
ansond 18:7dc9b949bbc3 586
ansond 18:7dc9b949bbc3 587 /**
ansond 18:7dc9b949bbc3 588 Retrieve the last executed update, upsert, or delete response error detail
ansond 18:7dc9b949bbc3 589 @return http response code from last update, upsert, or delete operation
ansond 18:7dc9b949bbc3 590 */
ansond 18:7dc9b949bbc3 591 MbedJSONValue getLastError();
ansond 9:a254fcd904be 592
ansond 9:a254fcd904be 593 protected:
ansond 15:89044c68ad36 594 // do we have a valid salesforce token and OAUTH token?
ansond 14:3c8d11b48814 595 bool haveSalesforceToken(bool fetch = true);
ansond 9:a254fcd904be 596
ansond 14:3c8d11b48814 597 // CREATE: a record in Salesforce.com
ansond 14:3c8d11b48814 598 char *createRecord(char *object_name,char *json_data,char *output_buffer,int output_buffer_length);
ansond 9:a254fcd904be 599
ansond 14:3c8d11b48814 600 // READ: a specific record in Salesforce.com
ansond 16:3d160f224084 601 char *readRecord(char *object_name,char *record_id,char *record_value,char *output_buffer,int output_buffer_length);
ansond 9:a254fcd904be 602
ansond 14:3c8d11b48814 603 // UPDATE: a specific record in Salesforce.com
ansond 18:7dc9b949bbc3 604 bool updateRecord(char *object_name,char *record_id,char *json_data,char *output_buffer,int output_buffer_length);
ansond 16:3d160f224084 605
ansond 16:3d160f224084 606 // UPSERT: update/insert a specific External record in Salesforce.com
ansond 18:7dc9b949bbc3 607 bool upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,char *json_data,char *output_buffer,int output_buffer_length);
ansond 9:a254fcd904be 608
ansond 18:7dc9b949bbc3 609 // DELETE: delete a specific record in Salesforce.com
ansond 18:7dc9b949bbc3 610 bool deleteRecord(char *object_name,char *record_id,char *output_buffer,int output_buffer_length);
ansond 18:7dc9b949bbc3 611
ansond 8:47db53cd5884 612 // raw invocation of REST calls into Salesforce.com
ansond 9:a254fcd904be 613 char *invoke(const char *url,char *output_buffer,int output_buffer_length); // defaults to GET
ansond 9:a254fcd904be 614 char *invoke(const char *url,char *output_buffer,int output_buffer_length,HttpVerb verb); // GET or DELETE with simple output
ansond 9:a254fcd904be 615 char *invoke(const char *url,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length); // defaults to POST with JSON input data type
ansond 9:a254fcd904be 616 char *invoke(const char *url,const InputDataTypes input_type,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length); // defaults to POST with variable input data type
ansond 9:a254fcd904be 617 char *invoke(const char *url,const InputDataTypes input_type,const char *input_data,const int input_data_len,char *output_buffer,int output_buffer_length,const HttpVerb verb); // full fidelity method
ansond 9:a254fcd904be 618
ansond 0:518b1ca956fc 619 // get our OAUTH Token
ansond 9:a254fcd904be 620 void checkAndGetOauthToken(bool fetch = true);
ansond 0:518b1ca956fc 621 char *getOauthToken(char *output_buffer,int output_buffer_length);
ansond 8:47db53cd5884 622
ansond 0:518b1ca956fc 623 // convenience accessors
ansond 21:e5a4471a46fb 624 Logger *logger();
ansond 0:518b1ca956fc 625 HTTPClient *http();
ansond 7:97ea5ef906f7 626 OauthToken *oauth();
ansond 7:97ea5ef906f7 627 HTTPResult httpStatus();
ansond 7:97ea5ef906f7 628
ansond 7:97ea5ef906f7 629 // internal checkers
ansond 0:518b1ca956fc 630 bool haveCreds();
ansond 7:97ea5ef906f7 631 void resetOauthToken();
ansond 7:97ea5ef906f7 632 void fillOauthToken(char *token);
ansond 9:a254fcd904be 633 bool validOauthToken(bool fetch = true);
ansond 8:47db53cd5884 634
ansond 14:3c8d11b48814 635 // get the specified URL from our Salesforce Token
ansond 8:47db53cd5884 636 char *getSalesforceURL(char *key,char *url_buffer,int url_buffer_length);
ansond 9:a254fcd904be 637
ansond 8:47db53cd5884 638 // simple char array replacement (modifies input string!)
ansond 8:47db53cd5884 639 void replace(char *str,char orig_char,char new_char);
ansond 8:47db53cd5884 640
ansond 8:47db53cd5884 641 // needed to replace substrings within std::string
ansond 8:47db53cd5884 642 void replace(string& line, string& oldString, string& newString);
ansond 17:6c774354b599 643
ansond 17:6c774354b599 644 // validate that http status is in the "n" range
ansond 17:6c774354b599 645 bool httpResponseCodeInRange(int n);
ansond 20:0d6abaf6d7c5 646
ansond 20:0d6abaf6d7c5 647 // min() method
ansond 20:0d6abaf6d7c5 648 int min(int value1,int value2);
ansond 21:e5a4471a46fb 649
ansond 22:3363752cd523 650 // look for a specific key value pair in a json message
ansond 22:3363752cd523 651 bool contains(char *json,char *key,char *value);
ansond 22:3363752cd523 652
ansond 21:e5a4471a46fb 653 // initialize
ansond 21:e5a4471a46fb 654 void init(HTTPClient *http,Logger *logger,bool logger_internal);
ansond 0:518b1ca956fc 655 };
ansond 0:518b1ca956fc 656
ansond 0:518b1ca956fc 657 #endif // _SALESFORCE_INTERFACE_H_