Axeda Ready Demo for Freescale FRDM-KL46Z as accident alert system

Dependencies:   FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem

Fork of AxedaGo-Freescal_FRDM-KL46Z revert by Axeda Corp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers axPlatform.c Source File

axPlatform.c

00001 /************************************************************************************/
00002 /* axPlatform.c                                                                    */
00003 /* 2013 Axeda Corporation                                                          */
00004 /*                                                                                  */
00005 /* Defines methods for interaction with end points on the Axeda Platform.  This     */
00006 /* is a device independent implementation which can be applied to any device that   */
00007 /* supports ANSI C.                                                                 */
00008 /************************************************************************************/
00009 
00010 #include "axPlatform.h"
00011 #include "axStatusCodes.h"
00012 #include <string.h>
00013 #include <stdlib.h>
00014 #include "axTransport.h"
00015 #include "axSerializer.h"
00016 #include "cJSON.h"
00017 #include "axConstants.h"
00018 #include "axHTTP.h"
00019 
00020 int handleResponse(HTTP_Transmission *response);
00021 
00022 static const char *endpoints[8]= { "ammp", "data", "assets", "files", " ", "packages", "status", " "};
00023 static const char *contentTypes[]= { "application/json", "multipart/form-data"};
00024 static const char *buffer_keywords[]= {"alarms", "events", "data", "locations" };
00025 
00026 const char URL_SEP='/';
00027 const char ID_SEP='!';
00028 
00029 /************************************************************************************/
00030 /*ax_platform_upload()                                                              */
00031 /*                                                                                  */
00032 /*file(required) : a pointer to a structure that the data will be stored in.        */
00033 /*name (required): a file name for the file. Can be arbitrarily assigned based on   */
00034 /*                 source of the data.                                              */
00035 /*hint(required): a string that allows you to tag the file for later retrieval      */
00036 /*size(optional): should be populated if the data does not have an EOF character at */
00037 /*                the end. If sending a memory block this will define the offset.   */
00038 /*data(required): a pointer to the data that will be sent as this file              */
00039 /*                                                                                  */
00040 /*                                                                                  */
00041 /************************************************************************************/
00042 int ax_platform_upload(ax_platform *cloud, ax_deviceID *device, ax_file *file)
00043   {
00044   int retVal=AX_UNKNOWN;
00045   char *url=NULL;
00046   HTTP_Part fileDat;
00047   HTTP_Transmission response;
00048   fileDat.data=file->data;
00049   fileDat.data_sz=file->size;
00050   fileDat.file_name=file->name;
00051   fileDat.hint=file->hint;
00052   fileDat.next=NULL;
00053 
00054   url = getFileResource(url, device);
00055 
00056   int body_sz=strlen(file->hint)+12+strlen(file->name);
00057   char *body=malloc(sizeof(char)*body_sz);
00058   int bodyWrt=snprintf(body, body_sz, "name=\"hint\" \r\n %s",file->hint);
00059   if(bodyWrt>body_sz) { retVal=AX_GEN_STR_TRUNC; }
00060   printDebug(body);
00061 
00062   retVal=http_send_mpost(url, cloud->hostname, cloud->port, cloud->secure, NULL, NULL, 0, &fileDat, 1, &response);
00063 
00064   free(body);
00065   free(url);
00066 
00067 return retVal;
00068 }
00069 
00070 /************************************************************************************/
00071 /* ax_platform_ping()                                                               */
00072 /*                                                                                  */
00073 /* This function creates a ping message which acts as the device heartbeat.         */
00074 /*                                                                                  */
00075 /*                                                                                  */
00076 /************************************************************************************/
00077 int ax_platform_ping(ax_platform *cloud, ax_deviceID *device)
00078   {
00079   int retVal=AX_UNKNOWN;
00080   char *url=NULL;
00081   HTTP_Headers myHeader;
00082   HTTP_Transmission response;
00083   myHeader.contentType=getGeneralType(myHeader.contentType);
00084   url=getAgentResource(url, device);
00085 
00086 //Send the request
00087   retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, NULL, 0, &response);
00088 //Scan the response and act if there are egress messages.
00089   handleResponse(&response);
00090   free(url);
00091   return retVal;
00092   }
00093 
00094 /************************************************************************************/
00095 /*ax_platform_download()                                                            */
00096 /*                                                                                  */
00097 /*This function wil request a file from the platform with a specific file ID.  The  */
00098 /*fileID itself will be transmitted down on a response message from the platform.   */
00099 /*                                                                                  */
00100 /*                                                                                  */
00101 /************************************************************************************/
00102 int ax_platform_download(ax_platform *cloud, ax_deviceID *device, ax_package_instruction *instr)
00103   {
00104     int retVal = AX_UNKNOWN;
00105     char *url=NULL;
00106     HTTP_Transmission response;
00107     url=getFileDownloadResource(url, device, instr->file_id);
00108     retVal=http_send_get(url, cloud->hostname, cloud->port, cloud->secure, &response);
00109 //TODO: revisit what to do with response in this case.
00110     scm_file_write(instr->filename, response.body, response.body_length, instr);
00111     free(url);
00112     return retVal;
00113   }
00114 
00115 
00116 /************************************************************************************/
00117 /* ax_platform_register()                                                           */
00118 /*                                                                                  */
00119 /*This function creates a registration message to be sent to the cloud. The message */
00120 /*contains information about the model, serial and expected ping interval. It also  */
00121 /*allows the cloud to mark the device as online. If using the standalone thread func*/
00122 /*-tion this method will be called automatically until successful.                  */
00123 /*                                                                                  */
00124 /*cloud(required) : a pointer to a structure that contains data about the cloud     */
00125 /*device(required) : a pointer to a structure that contains the model and serial    */
00126 /*pingRate(required) : an integer in milliseconds which tells the cloud how often to*/
00127 /*                     expect a heartbeat ping                                      */
00128 /*                                                                                  */
00129 /*Returns: an integer value indicating whether or not it successfully registered    */
00130 /************************************************************************************/
00131 int ax_platform_register(ax_platform *cloud, ax_deviceID *device)
00132   {
00133   int retVal=AX_UNKNOWN;
00134   char *url=NULL;
00135   char *fullRequest=NULL;
00136   cJSON *requestBody;
00137   HTTP_Headers myHeader;
00138   HTTP_Transmission response;
00139   myHeader.contentType=getGeneralType(myHeader.contentType);
00140   url = getRegistrationResource(url, device);
00141   int urlLength=strlen(url);
00142   url[urlLength]='\0';
00143 
00144   requestBody=getRegistrationJSON(device, cloud->ping_rate);
00145 
00146   fullRequest=cJSON_PrintUnformatted(requestBody);
00147   int contentLength=strlen(fullRequest);
00148 
00149   retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, contentLength, &response);
00150 //Scan the response and act if there are egress messages.
00151   handleResponse(&response);
00152 
00153 //Clean up after ourselves
00154   free(fullRequest);
00155   free(url);
00156   cJSON_Delete(requestBody);
00157   return retVal;
00158   }
00159 
00160 /**************************************************************************************/
00161 /*ax_platform_send()                                                                  */
00162 /*                                                                                    */
00163 /*This function sends any data available in the structures directly to the cloud in   */
00164 /*an on demand fashion.                                                               */
00165 /*                                                                                    */
00166 /*                                                                                    */
00167 /*cloud(required) : a pointer to a structure that contains the cloud service info     */
00168 /*device(required) : a pointer to a structure that contains device information        */
00169 /*dataItems(optional) : a pointer to an array of ax_dataItem pointers that will be sent*/
00170 /*alarms(optional) : a pointer to an array of ax_alarm pointers that will be sent      */
00171 /*events(optional) : a pointer to an array of ax_event pointers that will be sent      */
00172 /*locations(optional) : a pointer to an array of ax_location pointers that will be sent*/
00173 /*                                                                                     */
00174 /*Returns: an integer value indicating whether or not it successfully sent the data    */
00175 /**************************************************************************************/
00176 int ax_platform_send(ax_platform *cloud, ax_deviceID *device, ax_dataSet *dataItems[], int numDataSets, ax_alarm *alarms[], int numAlarms, ax_event *events[], int numEvents, ax_location *locations[], int numLocations) {
00177   
00178   int retVal=AX_UNKNOWN;
00179   HTTP_Headers myHeader;
00180   char *url=NULL;
00181   
00182   char *fullRequest=NULL;
00183   cJSON *rootNode=NULL;
00184   rootNode=cJSON_CreateObject();
00185   HTTP_Transmission response;
00186   zeroOutHTTPXmission(&response);
00187   //add the data in the DataItems queue if passed
00188   if(dataItems){
00189       cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_DATA], dataSet2JSON((ax_dataSet **)dataItems, numDataSets, terse_enable));
00190       }
00191   //add all alarms to the transmission if passed
00192   if(alarms){
00193     cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_ALARMS], AlarmsToJSON((ax_alarm **)alarms, numAlarms, terse_enable));
00194     }
00195   if(events){
00196     cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_EVENTS], eventsToJSON((ax_event **)events, numEvents, terse_enable));
00197   }
00198   if(locations){
00199     cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_LOCATIONS], locationsToJSON((ax_location **)locations, numLocations, terse_enable));
00200   }
00201 
00202   myHeader.contentType=getGeneralType(myHeader.contentType);
00203   url = getDataResource(url, device);
00204   fullRequest=cJSON_PrintUnformatted(rootNode);
00205 
00206   retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, strlen(fullRequest), &response);
00207 //Scan the response and act if there are egress messages.
00208   handleResponse(&response);
00209 
00210   if(fullRequest) {
00211   free(fullRequest);
00212   }
00213   free(url);
00214   cJSON_Delete(rootNode);
00215 
00216 return retVal;
00217   }
00218 
00219 /**************************************************************************************/
00220 /*ax_platform_sendData()                                                              */
00221 /*                                                                                    */
00222 /*This function immedately sends any data included in the parameter to the platform   */
00223 /*listed. It makes use of the ax_platform_send() function as a special case.          */
00224 /*                                                                                    */
00225 /*cloud(required) : a pointer to a structure that contains the cloud service info     */
00226 /*device(required) : a pointer to a structure that contains device information        */
00227 /*dataItems(required) : pointer to an array of ax_dataItem pointers that will be sent */
00228 /*                                                                                     */
00229 /*Returns: an integer value indicating whether or not it successfully sent the data    */
00230 /**************************************************************************************/
00231 int ax_platform_sendData(ax_platform *cloud, ax_deviceID *device, ax_dataSet *dataItems[], int numDataSets) {
00232 
00233 return ax_platform_send(cloud, device, dataItems, numDataSets, NULL, 0, NULL, 0, NULL, 0);
00234 
00235 }
00236 /**************************************************************************************/
00237 /*ax_platform_sendAlarms()                                                            */
00238 /*                                                                                    */
00239 /*This function immedately sends any alarms included in the parameter to the platform */
00240 /*listed. It makes use of the ax_platform_send() function as a special case.          */
00241 /*                                                                                    */
00242 /*cloud(required) : a pointer to a structure that contains the cloud service info     */
00243 /*device(required) : a pointer to a structure that contains device information        */
00244 /*alarms(required) : a pointer to an array of ax_alarm pointers that will be sent     */
00245 /*                                                                                     */
00246 /*Returns: an integer value indicating whether or not it successfully sent the data    */
00247 /**************************************************************************************/
00248 int ax_platform_sendAlarms(ax_platform *cloud, ax_deviceID *device, ax_alarm *alarms[], int numAlarms) {
00249 
00250 return ax_platform_send(cloud, device, NULL, 0, alarms, numAlarms, NULL, 0, NULL, 0);
00251 
00252 }
00253 /**************************************************************************************/
00254 /*ax_platform_sendEvents()                                                            */
00255 /*                                                                                    */
00256 /*This function immedately sends any events included in the parameter to the platform */
00257 /*listed. It makes use of the ax_platform_send() function as a special case.          */
00258 /*                                                                                    */
00259 /*cloud(required) : a pointer to a structure that contains the cloud service info     */
00260 /*device(required) : a pointer to a structure that contains device information        */
00261 /*events(required) : a pointer to an array of ax_event pointers that will be sent     */
00262 /*                                                                                     */
00263 /*Returns: an integer value indicating whether or not it successfully sent the data    */
00264 /**************************************************************************************/
00265 int ax_platform_sendEvents(ax_platform *cloud, ax_deviceID *device, ax_event *events[], int numEvents) {
00266 
00267 return ax_platform_send(cloud, device, NULL, 0, NULL, 0, events, numEvents, NULL, 0);
00268 
00269 }
00270 /**************************************************************************************/
00271 /*ax_platform_sendLocations()                                                         */
00272 /*                                                                                    */
00273 /*This function immedately sends any events included in the parameter to the platform */
00274 /*listed. It makes use of the ax_platform_send() function as a special case.          */
00275 /*                                                                                    */
00276 /*cloud(required) : a pointer to a structure that contains the cloud service info     */
00277 /*device(required) : a pointer to a structure that contains device information        */
00278 /*locations(required) : a pointer to an array of ax_location poitners that will be sent*/
00279 /*                                                                                     */
00280 /*Returns: an integer value indicating whether or not it successfully sent the data    */
00281 /**************************************************************************************/
00282 int ax_platform_sendLocations(ax_platform *cloud, ax_deviceID *device, ax_location *locations[], int numLocations) {
00283 
00284 return ax_platform_send(cloud, device, NULL, 0, NULL, 0, NULL, 0, locations, numLocations);
00285 
00286 }
00287 
00288 /**************************************************************************************/
00289 /*ax_platform_setPkgStatus()                                                          */
00290 /*                                                                                    */
00291 /*Tells the platform what state the package is currently in. This is necessary for the*/
00292 /*lifecycle of the packages in the Axeda System.                                      */
00293 /*                                                                                    */
00294 /**************************************************************************************/
00295 int ax_platform_setPkgStatus(ax_platform *cloud, ax_deviceID *device, char *pkgID, int status, char *errorMsg) {
00296   int retVal=AX_UNKNOWN;
00297   char *url=NULL;
00298   char *fullRequest=NULL;
00299   cJSON *requestBody=NULL; 
00300   HTTP_Headers myHeader;
00301   HTTP_Transmission response;
00302   zeroOutHTTPXmission(&response);
00303  
00304   requestBody= getPKGStatusJSON(status, errorMsg, AX_NO_PRIORITY, 0, terse_enable);  
00305 
00306   myHeader.contentType=getGeneralType(myHeader.contentType);
00307   url=getPackageUpdateResource(url, device, pkgID);
00308   int urlLength=strlen(url);
00309   url[urlLength]='\0'; 
00310  
00311   fullRequest=cJSON_PrintUnformatted(requestBody);
00312   int contentLength=strlen(fullRequest);
00313 //Send the status
00314   retVal=http_send_put(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, contentLength, &response);
00315 //Scan the response and act if there are egress messages.
00316   handleResponse(&response);
00317 
00318 //Clean up after ourselves
00319   free(fullRequest);
00320   free(url);
00321   cJSON_Delete(requestBody); 
00322 
00323   return retVal;  
00324   }
00325 /**************************************************************************************/
00326 /*ax_platform_setPkgStatus()                                                          */
00327 /*                                                                                    */
00328 /*Tells the platform what state the package is currently in. This is necessary for the*/
00329 /*lifecycle of the packages in the Axeda System.                                      */
00330 /*                                                                                    */
00331 /**************************************************************************************/
00332 int ax_platform_setPkgStatusStarted(ax_platform *cloud, ax_deviceID *device, char *pkgID) {
00333   return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_STARTED, NULL);
00334   }
00335 /**************************************************************************************/
00336 /*ax_platform_setPkgStatus()                                                          */
00337 /*                                                                                    */
00338 /*Tells the platform what state the package is currently in. This is necessary for the*/
00339 /*lifecycle of the packages in the Axeda System.                                      */
00340 /*                                                                                    */
00341 /**************************************************************************************/
00342 int ax_platform_setPkgStatusQueued(ax_platform *cloud, ax_deviceID *device, char *pkgID) {
00343   return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_QUEUED, NULL);
00344   }
00345 /**************************************************************************************/
00346 /*ax_platform_setPkgStatus()                                                          */
00347 /*                                                                                    */
00348 /*Tells the platform what state the package is currently in. This is necessary for the*/
00349 /*lifecycle of the packages in the Axeda System.                                      */
00350 /*                                                                                    */
00351 /**************************************************************************************/
00352 int ax_platform_setPkgStatusSuccess(ax_platform *cloud, ax_deviceID *device, char *pkgID) {
00353   return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_SUCCESS, NULL);
00354   }
00355 /**************************************************************************************/
00356 /*ax_platform_setPkgStatus()                                                          */
00357 /*                                                                                    */
00358 /*Tells the platform what state the package is currently in. This is necessary for the*/
00359 /*lifecycle of the packages in the Axeda System.                                      */
00360 /*                                                                                    */
00361 /**************************************************************************************/
00362 int ax_platform_setPkgStatusFailed(ax_platform *cloud, ax_deviceID *device, char *pkgID, char *errorMsg) {
00363   return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_FAILURE, errorMsg);
00364   }
00365 
00366 /***************************************************************************************************************************************************************/
00367 /***************************************************************************************************************************************************************/
00368 /*The code in the following sections should never need to be called as it will be called from the preceeding functions.                                        */
00369 /***************************************************************************************************************************************************************/
00370 /***************************************************************************************************************************************************************/
00371 
00372 /************************************************************************************/
00373 /* The following methods construct references to endpoints on the platform where the */
00374 /*respective data will be sent. For the sake of convenience they all return a pointer*/
00375 /*that is equal in value to that which was passed in.                                */
00376 /* They all take the same arguments:                                                 */
00377 /*                                                                                   */
00378 /* endPointBuff = The pointer to where the endpoint will be stored. This pointer    */
00379 /*                will be  allocated and populated by the function                   */
00380 /* ax_deviceID = A structure that contains the model and serial number of the current*/
00381 /*               device. This structure should be the same as the one constructed at */
00382 /*               startup based on the arguments.                                     */
00383 /************************************************************************************/
00384 char *getDataResource(char *endPointBuff, ax_deviceID *device)
00385    {
00386    return getResource(endPointBuff, device, END_DATA);
00387    }
00388 
00389 char *getAgentResource(char *endPointBuff, ax_deviceID *device)
00390    {
00391    return getResource(endPointBuff, device, END_AGENTS);
00392    }
00393 
00394 char *getFileResource(char *endPointBuff, ax_deviceID *device)
00395    {
00396    return getResource(endPointBuff, device, END_FILES);
00397    }
00398 
00399 char *getRegistrationResource(char *endPointBuff, ax_deviceID *device)
00400    {
00401    return getResource(endPointBuff, device, END_REG);
00402    }
00403 char *getFileDownloadResource(char *endPointBuff, ax_deviceID *device, char *fileID) {
00404     //since this url is slightly different from all the others we need to override the standard passing.
00405     char *tempBuff=NULL;
00406     tempBuff=encodeAgentID(device, tempBuff);
00407     int len=strlen(endpoints[END_BASE])+strlen(endpoints[END_PACKAGES])+6+strlen(tempBuff)+strlen(fileID)+strlen(endpoints[END_FILES])+1+strlen(PROTOCOL_VERSION)+1;
00408     endPointBuff = (char *)calloc(len,sizeof(char));
00409     // /ammp/packages/1/files/test_model!test_serial/12345
00410     // , URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[END_FILED], URL_SEP, PROTOCOL_VERSION, URL_SEP, endpoints[END_FILES], URL_SEP, tempBuff=encodeAgentID(device, tempBuff), URL_SEP, fileID
00411     // %c%s%c%s%c%s%c%s%c%s%c%s
00412     
00413     snprintf(endPointBuff, len, "%c%s%c%s%c%s%c%s%c%s%c%s", URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[END_PACKAGES], URL_SEP, PROTOCOL_VERSION, URL_SEP, endpoints[END_FILES], URL_SEP, tempBuff, URL_SEP, fileID );
00414     free(tempBuff);
00415 
00416     return endPointBuff;
00417 }
00418 
00419 char *getPackageUpdateResource(char *endPointBuff, ax_deviceID *device, char *packageID){
00420     //since this url is slightly different from all the others we need to override the standard passing.
00421     // "/ammp/packages/1/12345/status/test_model!test_serial"
00422     char *tempBuff=NULL;
00423     tempBuff=encodeAgentID(device, tempBuff);
00424     int len=6+strlen(endpoints[END_BASE])+strlen(endpoints[END_PACKAGES])+strlen(PROTOCOL_VERSION)+strlen(packageID)+strlen(endpoints[END_STATUS])+strlen(tempBuff)+1;
00425         endPointBuff = (char *)calloc(len, sizeof(char));
00426     
00427         snprintf(endPointBuff, len, "%c%s%c%s%c%s%c%s%c%s%c%s", URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[END_PACKAGES], URL_SEP, PROTOCOL_VERSION, URL_SEP, packageID, URL_SEP, endpoints[END_STATUS], URL_SEP, tempBuff);
00428         free(tempBuff);
00429 
00430         return endPointBuff;
00431     }
00432 
00433 char *getResource(char *endPointBuff, ax_deviceID *device, int resourceType)
00434   {
00435 //Check for bounds on the endpoints array. END_REG is currently the highest, if it's OOB return the agent default URL
00436   int resType=END_AGENTS;
00437   if((resourceType<0)||(resourceType>END_REG)) { resType=END_AGENTS; }
00438   else { resType=resourceType; }
00439   int len = strlen(endpoints[END_BASE])+strlen(endpoints[resType])+6+strlen(device->model)+strlen(device->serial);
00440        endPointBuff = (char *)calloc(len+1, sizeof(char));
00441         char *tempBuff=NULL;
00442          switch(resType) {
00443             case END_REG:
00444               snprintf(endPointBuff, len+1, "%c%s%c%s%c%s", URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[END_AGENTS], URL_SEP, PROTOCOL_VERSION);
00445             break;
00446             case END_FILED:
00447             
00448             break;
00449             default:
00450              snprintf(endPointBuff, len+1, "%c%s%c%s%c%s%c%s", URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[resType], URL_SEP, PROTOCOL_VERSION, URL_SEP, tempBuff=encodeAgentID(device, tempBuff));
00451              free(tempBuff); //only used for storing the deviceID it's work is done now.
00452             break;
00453          }
00454 
00455         return endPointBuff;
00456   }
00457 
00458 
00459 /**************************************************************************************/
00460 /*encodeAgentID()                                                                     */
00461 /*                                                                                    */
00462 /*A utility method to convert the ax_deviceID structure into a protocol compliant     */
00463 /*identifier string. Used mostly by the registration message                          */
00464 /*                                                                                    */
00465 /*device(required) : a pointer to a structure that contains the model, serial, tenant*/
00466 /*buff(required) : a pointer to a char array where the output will be stored.         */
00467 /*                                                                                    */
00468 /*Returns: a pointer to the char array, same as *buff                                 */
00469 /**************************************************************************************/
00470 char* encodeAgentID(ax_deviceID *device, char *buff)
00471  {
00472     //TODO: Add logic to URL Encode output string if special characters are encountered...
00473  int len=0;
00474 if(strlen(device->tenant)>0)
00475     {
00476     len=strlen(device->model)+strlen(device->serial)+strlen(device->tenant)+4;
00477     buff = (char *)calloc(len, sizeof(char));
00478     //buff[len]='\0';
00479     snprintf(buff, len, "%s@%s!%s", device->model, device->tenant, device->serial );
00480     }
00481  else
00482     {
00483     len=strlen(device->model)+strlen(device->serial)+3;
00484     buff = (char *)calloc(len, sizeof(char));
00485     //buff[len]='\0';
00486     snprintf(buff,len, "%s!%s", device->model, device->serial);
00487     }
00488 
00489     printDebug(buff);
00490 
00491  return buff;
00492  }
00493 
00494 /**************************************************************************************/
00495 /*getContentType()                                                                    */
00496 /*                                                                                    */
00497 /*A convenience method to allow different messages to have different media types. The */
00498 /*media types are set forth in the protocol specification. The function will return a */
00499 /*a pointer to a declared string, for which you do not need to free.                   */
00500 /*                                                                                    */
00501 /*                                                                                    */
00502 /*                                                                                    */
00503 /**************************************************************************************/
00504 
00505 char *getContentType(char *contentBuff, int type) {
00506     switch(type) {
00507         case 0:
00508           contentBuff=(char *)contentTypes[MIME_JSON];
00509           break;
00510         default:
00511           contentBuff=(char *)contentTypes[MIME_JSON];
00512           break;
00513         }
00514     return contentBuff;
00515 }
00516 
00517 char *getGeneralType(char *contentBuff) {
00518     return getContentType(contentBuff, TRANS_TYPE_JSON);
00519     }
00520 
00521 /**************************************************************************************/
00522 /*int handleResponse()                                                                */
00523 /*                                                                                    */
00524 /*A catch-all method that will handle any egress messages sent from the platform back */
00525 /*to the device. If the JSON returned is valid it will dispatch the requests as needed*/
00526 /*                                                                                    */
00527 /*                                                                                    */
00528 /*                                                                                    */
00529 /**************************************************************************************/
00530 //Possible returns:
00531 // AX_EGR_JSON_PARSE_FAIL -- A failure to parse the JSON that was returned
00532 
00533 int handleResponse(HTTP_Transmission *response){
00534     cJSON *resp_int, *temp, *temp_child, *instructions, *instruction_child;
00535     int retVal=AX_OK;
00536     if(response->body==NULL) {return AX_OK;} //if there's no body, there's nothing to do here.
00537 
00538     resp_int=cJSON_Parse(response->body);
00539     if(resp_int==NULL) {
00540         return AX_GEN_PARSE_ERR;
00541         }
00542   printDebug("Creating software packages\n");
00543     temp=cJSON_GetObjectItem(resp_int, "packages");
00544     if(temp!=NULL) {
00545         //Handle a software package here
00546         int ctr=0, pkg_ctr2=0;
00547         int sz=cJSON_GetArraySize(temp);
00548         int instructionCt=0;
00549         ax_package *temp_package;
00550 
00551         for(ctr=0; ctr<sz; ctr++)
00552             {
00553             printDebug("Parsing package[]...\n");
00554             temp_child=cJSON_GetArrayItem(temp, ctr);
00555             //Create an ax_package for this
00556             temp_package=(ax_package *)malloc(sizeof(ax_package));
00557             char *pkgID=cJSON_GetObjectItem(temp_child, "id")->valuestring;
00558             retVal=ax_pkg_createPackage(temp_package, pkgID, 0, AX_NO_PRIORITY);         
00559             temp_package->priority=cJSON_GetObjectItem(temp_child, "priority")->valueint;
00560             temp_package->time=cJSON_GetObjectItem(temp_child, "time")->valueint;
00561             //add Instructions to the package
00562             instructions=cJSON_GetObjectItem(temp_child, "instructions");
00563             instructionCt=cJSON_GetArraySize(instructions);
00564                 for(pkg_ctr2=0; pkg_ctr2<instructionCt; pkg_ctr2++)
00565                   {
00566                   //int instrType=-1;
00567                   printDebug("Parsing instruction\n");
00568                   instruction_child=cJSON_GetArrayItem(instructions, pkg_ctr2);
00569                                     
00570                   if(strcmp("down", cJSON_GetObjectItem(instruction_child, "@type")->valuestring)==0) {
00571                       cJSON *id=cJSON_GetObjectItem(instruction_child, "id");
00572                       char *s_id = NULL;
00573                       if(id != NULL){
00574                         s_id=id->valuestring;
00575                       }
00576                       char *s_path = NULL;
00577                       //path is optional so we need to make sure it is here before trying to get the valuestring
00578                       cJSON *path = cJSON_GetObjectItem(instruction_child, "fp");
00579                       if(path != NULL){
00580                         s_path=path->valuestring;
00581                       }
00582                       else{
00583                           path = cJSON_GetObjectItem(instruction_child, "path");
00584                           if(path != NULL){
00585                             s_path=path->valuestring;
00586                           }
00587                       }
00588                       char *s_filename = NULL;
00589                       cJSON *fn = cJSON_GetObjectItem(instruction_child, "fn");
00590                       if(fn != NULL){
00591                             s_filename=fn->valuestring;
00592                       }
00593                       else{
00594                           path = cJSON_GetObjectItem(instruction_child, "filename");
00595                           if(path != NULL){
00596                             s_path=path->valuestring;
00597                           }
00598                       }
00599                       retVal=ax_pkg_addDLInstruction(temp_package, s_id, s_path, s_filename); 
00600                       }
00601                   //if it's not a download instruction, we don't care; down was the only one available in AMMP1.0
00602                   }
00603             //Now we tell someone that we've got a software package
00604             scm_download_req(temp_package); 
00605             }
00606         }
00607     int dictr1=0;
00608     //Set Data Item Commands will occur here.
00609      temp=NULL;
00610      temp_child=NULL;
00611      instructions=NULL;
00612      instruction_child=NULL;
00613 
00614      printDebug("Setting Data Item Commands\n");
00615     temp=cJSON_GetObjectItem(resp_int, "set");
00616     if(temp!=NULL){
00617         int disz=cJSON_GetArraySize(temp);
00618         for(dictr1=0; dictr1<disz; dictr1++)
00619              {
00620              temp_child=cJSON_GetArrayItem(temp, dictr1);
00621              instructions=cJSON_GetObjectItem(temp_child, "dataItems");
00622              instruction_child=instructions->child;
00623              while(instruction_child!=NULL){
00624                  if(instruction_child->type==cJSON_String) {
00625                      data_item_write(instruction_child->string, instruction_child->valuestring, 0, AX_STRING);
00626                      }
00627                  else if(instruction_child->type==cJSON_False) {
00628                      data_item_write(instruction_child->string, NULL, AX_FALSE, AX_DIGITAL);
00629                      }
00630                  else if(instruction_child->type==cJSON_True) {
00631                      data_item_write(instruction_child->string, NULL, AX_TRUE, AX_DIGITAL);
00632                      }
00633                  else {
00634                      data_item_write(instruction_child->string, NULL, instruction_child->valuedouble, AX_ANALOG);
00635                      }
00636                  instruction_child=instruction_child->next;
00637                  }
00638 
00639              }
00640          }
00641      //Data Item Poll requests here.
00642     printDebug("Setting Data Item Poll requests\n");
00643     int dictr2=0;
00644     temp=NULL;
00645     temp_child=NULL;
00646     instructions=NULL;
00647     instruction_child=NULL;
00648      temp=cJSON_GetObjectItem(resp_int, "send");
00649      if(temp!=NULL){
00650         int dissz=cJSON_GetArraySize(temp);
00651         for(dictr2=0; dictr2<dissz; dictr2++) {
00652             temp_child=cJSON_GetArrayItem(temp, dictr2);
00653             instructions=cJSON_GetObjectItem(temp_child, "dataItems");
00654             instruction_child=instructions->child;
00655             while(instruction_child!=NULL){
00656                 data_item_request(instruction_child->valuestring);
00657                 instruction_child=instruction_child->next;
00658                 }
00659             }
00660         }
00661 
00662     cJSON_Delete(resp_int);//dispose of the cJSON object
00663     free(response->body);
00664 
00665 
00666   return retVal;
00667   }
00668 
00669 
00670