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 by
Diff: AMMPC/axPlatform.c
- Revision:
- 0:65004368569c
diff -r 000000000000 -r 65004368569c AMMPC/axPlatform.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AMMPC/axPlatform.c Tue Jul 01 21:31:54 2014 +0000 @@ -0,0 +1,670 @@ +/************************************************************************************/ +/* axPlatform.c */ +/* 2013 Axeda Corporation */ +/* */ +/* Defines methods for interaction with end points on the Axeda Platform. This */ +/* is a device independent implementation which can be applied to any device that */ +/* supports ANSI C. */ +/************************************************************************************/ + +#include "axPlatform.h" +#include "axStatusCodes.h" +#include <string.h> +#include <stdlib.h> +#include "axTransport.h" +#include "axSerializer.h" +#include "cJSON.h" +#include "axConstants.h" +#include "axHTTP.h" + +int handleResponse(HTTP_Transmission *response); + +static const char *endpoints[8]= { "ammp", "data", "assets", "files", " ", "packages", "status", " "}; +static const char *contentTypes[]= { "application/json", "multipart/form-data"}; +static const char *buffer_keywords[]= {"alarms", "events", "data", "locations" }; + +const char URL_SEP='/'; +const char ID_SEP='!'; + +/************************************************************************************/ +/*ax_platform_upload() */ +/* */ +/*file(required) : a pointer to a structure that the data will be stored in. */ +/*name (required): a file name for the file. Can be arbitrarily assigned based on */ +/* source of the data. */ +/*hint(required): a string that allows you to tag the file for later retrieval */ +/*size(optional): should be populated if the data does not have an EOF character at */ +/* the end. If sending a memory block this will define the offset. */ +/*data(required): a pointer to the data that will be sent as this file */ +/* */ +/* */ +/************************************************************************************/ +int ax_platform_upload(ax_platform *cloud, ax_deviceID *device, ax_file *file) + { + int retVal=AX_UNKNOWN; + char *url=NULL; + HTTP_Part fileDat; + HTTP_Transmission response; + fileDat.data=file->data; + fileDat.data_sz=file->size; + fileDat.file_name=file->name; + fileDat.hint=file->hint; + fileDat.next=NULL; + + url = getFileResource(url, device); + + int body_sz=strlen(file->hint)+12+strlen(file->name); + char *body=malloc(sizeof(char)*body_sz); + int bodyWrt=snprintf(body, body_sz, "name=\"hint\" \r\n %s",file->hint); + if(bodyWrt>body_sz) { retVal=AX_GEN_STR_TRUNC; } + printDebug(body); + + retVal=http_send_mpost(url, cloud->hostname, cloud->port, cloud->secure, NULL, NULL, 0, &fileDat, 1, &response); + + free(body); + free(url); + +return retVal; +} + +/************************************************************************************/ +/* ax_platform_ping() */ +/* */ +/* This function creates a ping message which acts as the device heartbeat. */ +/* */ +/* */ +/************************************************************************************/ +int ax_platform_ping(ax_platform *cloud, ax_deviceID *device) + { + int retVal=AX_UNKNOWN; + char *url=NULL; + HTTP_Headers myHeader; + HTTP_Transmission response; + myHeader.contentType=getGeneralType(myHeader.contentType); + url=getAgentResource(url, device); + +//Send the request + retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, NULL, 0, &response); +//Scan the response and act if there are egress messages. + handleResponse(&response); + free(url); + return retVal; + } + +/************************************************************************************/ +/*ax_platform_download() */ +/* */ +/*This function wil request a file from the platform with a specific file ID. The */ +/*fileID itself will be transmitted down on a response message from the platform. */ +/* */ +/* */ +/************************************************************************************/ +int ax_platform_download(ax_platform *cloud, ax_deviceID *device, ax_package_instruction *instr) + { + int retVal = AX_UNKNOWN; + char *url=NULL; + HTTP_Transmission response; + url=getFileDownloadResource(url, device, instr->file_id); + retVal=http_send_get(url, cloud->hostname, cloud->port, cloud->secure, &response); +//TODO: revisit what to do with response in this case. + scm_file_write(instr->filename, response.body, response.body_length, instr); + free(url); + return retVal; + } + + +/************************************************************************************/ +/* ax_platform_register() */ +/* */ +/*This function creates a registration message to be sent to the cloud. The message */ +/*contains information about the model, serial and expected ping interval. It also */ +/*allows the cloud to mark the device as online. If using the standalone thread func*/ +/*-tion this method will be called automatically until successful. */ +/* */ +/*cloud(required) : a pointer to a structure that contains data about the cloud */ +/*device(required) : a pointer to a structure that contains the model and serial */ +/*pingRate(required) : an integer in milliseconds which tells the cloud how often to*/ +/* expect a heartbeat ping */ +/* */ +/*Returns: an integer value indicating whether or not it successfully registered */ +/************************************************************************************/ +int ax_platform_register(ax_platform *cloud, ax_deviceID *device) + { + int retVal=AX_UNKNOWN; + char *url=NULL; + char *fullRequest=NULL; + cJSON *requestBody; + HTTP_Headers myHeader; + HTTP_Transmission response; + myHeader.contentType=getGeneralType(myHeader.contentType); + url = getRegistrationResource(url, device); + int urlLength=strlen(url); + url[urlLength]='\0'; + + requestBody=getRegistrationJSON(device, cloud->ping_rate); + + fullRequest=cJSON_PrintUnformatted(requestBody); + int contentLength=strlen(fullRequest); + + retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, contentLength, &response); +//Scan the response and act if there are egress messages. + handleResponse(&response); + +//Clean up after ourselves + free(fullRequest); + free(url); + cJSON_Delete(requestBody); + return retVal; + } + +/**************************************************************************************/ +/*ax_platform_send() */ +/* */ +/*This function sends any data available in the structures directly to the cloud in */ +/*an on demand fashion. */ +/* */ +/* */ +/*cloud(required) : a pointer to a structure that contains the cloud service info */ +/*device(required) : a pointer to a structure that contains device information */ +/*dataItems(optional) : a pointer to an array of ax_dataItem pointers that will be sent*/ +/*alarms(optional) : a pointer to an array of ax_alarm pointers that will be sent */ +/*events(optional) : a pointer to an array of ax_event pointers that will be sent */ +/*locations(optional) : a pointer to an array of ax_location pointers that will be sent*/ +/* */ +/*Returns: an integer value indicating whether or not it successfully sent the data */ +/**************************************************************************************/ +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) { + + int retVal=AX_UNKNOWN; + HTTP_Headers myHeader; + char *url=NULL; + + char *fullRequest=NULL; + cJSON *rootNode=NULL; + rootNode=cJSON_CreateObject(); + HTTP_Transmission response; + zeroOutHTTPXmission(&response); + //add the data in the DataItems queue if passed + if(dataItems){ + cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_DATA], dataSet2JSON((ax_dataSet **)dataItems, numDataSets, terse_enable)); + } + //add all alarms to the transmission if passed + if(alarms){ + cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_ALARMS], AlarmsToJSON((ax_alarm **)alarms, numAlarms, terse_enable)); + } + if(events){ + cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_EVENTS], eventsToJSON((ax_event **)events, numEvents, terse_enable)); + } + if(locations){ + cJSON_AddItemToObject(rootNode, buffer_keywords[BUFF_LOCATIONS], locationsToJSON((ax_location **)locations, numLocations, terse_enable)); + } + + myHeader.contentType=getGeneralType(myHeader.contentType); + url = getDataResource(url, device); + fullRequest=cJSON_PrintUnformatted(rootNode); + + retVal= http_send_post(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, strlen(fullRequest), &response); +//Scan the response and act if there are egress messages. + handleResponse(&response); + + if(fullRequest) { + free(fullRequest); + } + free(url); + cJSON_Delete(rootNode); + +return retVal; + } + +/**************************************************************************************/ +/*ax_platform_sendData() */ +/* */ +/*This function immedately sends any data included in the parameter to the platform */ +/*listed. It makes use of the ax_platform_send() function as a special case. */ +/* */ +/*cloud(required) : a pointer to a structure that contains the cloud service info */ +/*device(required) : a pointer to a structure that contains device information */ +/*dataItems(required) : pointer to an array of ax_dataItem pointers that will be sent */ +/* */ +/*Returns: an integer value indicating whether or not it successfully sent the data */ +/**************************************************************************************/ +int ax_platform_sendData(ax_platform *cloud, ax_deviceID *device, ax_dataSet *dataItems[], int numDataSets) { + +return ax_platform_send(cloud, device, dataItems, numDataSets, NULL, 0, NULL, 0, NULL, 0); + +} +/**************************************************************************************/ +/*ax_platform_sendAlarms() */ +/* */ +/*This function immedately sends any alarms included in the parameter to the platform */ +/*listed. It makes use of the ax_platform_send() function as a special case. */ +/* */ +/*cloud(required) : a pointer to a structure that contains the cloud service info */ +/*device(required) : a pointer to a structure that contains device information */ +/*alarms(required) : a pointer to an array of ax_alarm pointers that will be sent */ +/* */ +/*Returns: an integer value indicating whether or not it successfully sent the data */ +/**************************************************************************************/ +int ax_platform_sendAlarms(ax_platform *cloud, ax_deviceID *device, ax_alarm *alarms[], int numAlarms) { + +return ax_platform_send(cloud, device, NULL, 0, alarms, numAlarms, NULL, 0, NULL, 0); + +} +/**************************************************************************************/ +/*ax_platform_sendEvents() */ +/* */ +/*This function immedately sends any events included in the parameter to the platform */ +/*listed. It makes use of the ax_platform_send() function as a special case. */ +/* */ +/*cloud(required) : a pointer to a structure that contains the cloud service info */ +/*device(required) : a pointer to a structure that contains device information */ +/*events(required) : a pointer to an array of ax_event pointers that will be sent */ +/* */ +/*Returns: an integer value indicating whether or not it successfully sent the data */ +/**************************************************************************************/ +int ax_platform_sendEvents(ax_platform *cloud, ax_deviceID *device, ax_event *events[], int numEvents) { + +return ax_platform_send(cloud, device, NULL, 0, NULL, 0, events, numEvents, NULL, 0); + +} +/**************************************************************************************/ +/*ax_platform_sendLocations() */ +/* */ +/*This function immedately sends any events included in the parameter to the platform */ +/*listed. It makes use of the ax_platform_send() function as a special case. */ +/* */ +/*cloud(required) : a pointer to a structure that contains the cloud service info */ +/*device(required) : a pointer to a structure that contains device information */ +/*locations(required) : a pointer to an array of ax_location poitners that will be sent*/ +/* */ +/*Returns: an integer value indicating whether or not it successfully sent the data */ +/**************************************************************************************/ +int ax_platform_sendLocations(ax_platform *cloud, ax_deviceID *device, ax_location *locations[], int numLocations) { + +return ax_platform_send(cloud, device, NULL, 0, NULL, 0, NULL, 0, locations, numLocations); + +} + +/**************************************************************************************/ +/*ax_platform_setPkgStatus() */ +/* */ +/*Tells the platform what state the package is currently in. This is necessary for the*/ +/*lifecycle of the packages in the Axeda System. */ +/* */ +/**************************************************************************************/ +int ax_platform_setPkgStatus(ax_platform *cloud, ax_deviceID *device, char *pkgID, int status, char *errorMsg) { + int retVal=AX_UNKNOWN; + char *url=NULL; + char *fullRequest=NULL; + cJSON *requestBody=NULL; + HTTP_Headers myHeader; + HTTP_Transmission response; + zeroOutHTTPXmission(&response); + + requestBody= getPKGStatusJSON(status, errorMsg, AX_NO_PRIORITY, 0, terse_enable); + + myHeader.contentType=getGeneralType(myHeader.contentType); + url=getPackageUpdateResource(url, device, pkgID); + int urlLength=strlen(url); + url[urlLength]='\0'; + + fullRequest=cJSON_PrintUnformatted(requestBody); + int contentLength=strlen(fullRequest); +//Send the status + retVal=http_send_put(url, cloud->hostname, cloud->port, cloud->secure, &myHeader, fullRequest, contentLength, &response); +//Scan the response and act if there are egress messages. + handleResponse(&response); + +//Clean up after ourselves + free(fullRequest); + free(url); + cJSON_Delete(requestBody); + + return retVal; + } +/**************************************************************************************/ +/*ax_platform_setPkgStatus() */ +/* */ +/*Tells the platform what state the package is currently in. This is necessary for the*/ +/*lifecycle of the packages in the Axeda System. */ +/* */ +/**************************************************************************************/ +int ax_platform_setPkgStatusStarted(ax_platform *cloud, ax_deviceID *device, char *pkgID) { + return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_STARTED, NULL); + } +/**************************************************************************************/ +/*ax_platform_setPkgStatus() */ +/* */ +/*Tells the platform what state the package is currently in. This is necessary for the*/ +/*lifecycle of the packages in the Axeda System. */ +/* */ +/**************************************************************************************/ +int ax_platform_setPkgStatusQueued(ax_platform *cloud, ax_deviceID *device, char *pkgID) { + return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_QUEUED, NULL); + } +/**************************************************************************************/ +/*ax_platform_setPkgStatus() */ +/* */ +/*Tells the platform what state the package is currently in. This is necessary for the*/ +/*lifecycle of the packages in the Axeda System. */ +/* */ +/**************************************************************************************/ +int ax_platform_setPkgStatusSuccess(ax_platform *cloud, ax_deviceID *device, char *pkgID) { + return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_SUCCESS, NULL); + } +/**************************************************************************************/ +/*ax_platform_setPkgStatus() */ +/* */ +/*Tells the platform what state the package is currently in. This is necessary for the*/ +/*lifecycle of the packages in the Axeda System. */ +/* */ +/**************************************************************************************/ +int ax_platform_setPkgStatusFailed(ax_platform *cloud, ax_deviceID *device, char *pkgID, char *errorMsg) { + return ax_platform_setPkgStatus(cloud, device, pkgID, AX_PKG_FAILURE, errorMsg); + } + +/***************************************************************************************************************************************************************/ +/***************************************************************************************************************************************************************/ +/*The code in the following sections should never need to be called as it will be called from the preceeding functions. */ +/***************************************************************************************************************************************************************/ +/***************************************************************************************************************************************************************/ + +/************************************************************************************/ +/* The following methods construct references to endpoints on the platform where the */ +/*respective data will be sent. For the sake of convenience they all return a pointer*/ +/*that is equal in value to that which was passed in. */ +/* They all take the same arguments: */ +/* */ +/* endPointBuff = The pointer to where the endpoint will be stored. This pointer */ +/* will be allocated and populated by the function */ +/* ax_deviceID = A structure that contains the model and serial number of the current*/ +/* device. This structure should be the same as the one constructed at */ +/* startup based on the arguments. */ +/************************************************************************************/ +char *getDataResource(char *endPointBuff, ax_deviceID *device) + { + return getResource(endPointBuff, device, END_DATA); + } + +char *getAgentResource(char *endPointBuff, ax_deviceID *device) + { + return getResource(endPointBuff, device, END_AGENTS); + } + +char *getFileResource(char *endPointBuff, ax_deviceID *device) + { + return getResource(endPointBuff, device, END_FILES); + } + +char *getRegistrationResource(char *endPointBuff, ax_deviceID *device) + { + return getResource(endPointBuff, device, END_REG); + } +char *getFileDownloadResource(char *endPointBuff, ax_deviceID *device, char *fileID) { + //since this url is slightly different from all the others we need to override the standard passing. + char *tempBuff=NULL; + tempBuff=encodeAgentID(device, tempBuff); + int len=strlen(endpoints[END_BASE])+strlen(endpoints[END_PACKAGES])+6+strlen(tempBuff)+strlen(fileID)+strlen(endpoints[END_FILES])+1+strlen(PROTOCOL_VERSION)+1; + endPointBuff = (char *)calloc(len,sizeof(char)); + // /ammp/packages/1/files/test_model!test_serial/12345 + // , 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 + // %c%s%c%s%c%s%c%s%c%s%c%s + + 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 ); + free(tempBuff); + + return endPointBuff; +} + +char *getPackageUpdateResource(char *endPointBuff, ax_deviceID *device, char *packageID){ + //since this url is slightly different from all the others we need to override the standard passing. + // "/ammp/packages/1/12345/status/test_model!test_serial" + char *tempBuff=NULL; + tempBuff=encodeAgentID(device, tempBuff); + int len=6+strlen(endpoints[END_BASE])+strlen(endpoints[END_PACKAGES])+strlen(PROTOCOL_VERSION)+strlen(packageID)+strlen(endpoints[END_STATUS])+strlen(tempBuff)+1; + endPointBuff = (char *)calloc(len, sizeof(char)); + + 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); + free(tempBuff); + + return endPointBuff; + } + +char *getResource(char *endPointBuff, ax_deviceID *device, int resourceType) + { +//Check for bounds on the endpoints array. END_REG is currently the highest, if it's OOB return the agent default URL + int resType=END_AGENTS; + if((resourceType<0)||(resourceType>END_REG)) { resType=END_AGENTS; } + else { resType=resourceType; } + int len = strlen(endpoints[END_BASE])+strlen(endpoints[resType])+6+strlen(device->model)+strlen(device->serial); + endPointBuff = (char *)calloc(len+1, sizeof(char)); + char *tempBuff=NULL; + switch(resType) { + case END_REG: + snprintf(endPointBuff, len+1, "%c%s%c%s%c%s", URL_SEP, endpoints[END_BASE], URL_SEP, endpoints[END_AGENTS], URL_SEP, PROTOCOL_VERSION); + break; + case END_FILED: + + break; + default: + 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)); + free(tempBuff); //only used for storing the deviceID it's work is done now. + break; + } + + return endPointBuff; + } + + +/**************************************************************************************/ +/*encodeAgentID() */ +/* */ +/*A utility method to convert the ax_deviceID structure into a protocol compliant */ +/*identifier string. Used mostly by the registration message */ +/* */ +/*device(required) : a pointer to a structure that contains the model, serial, tenant*/ +/*buff(required) : a pointer to a char array where the output will be stored. */ +/* */ +/*Returns: a pointer to the char array, same as *buff */ +/**************************************************************************************/ +char* encodeAgentID(ax_deviceID *device, char *buff) + { + //TODO: Add logic to URL Encode output string if special characters are encountered... + int len=0; +if(strlen(device->tenant)>0) + { + len=strlen(device->model)+strlen(device->serial)+strlen(device->tenant)+4; + buff = (char *)calloc(len, sizeof(char)); + //buff[len]='\0'; + snprintf(buff, len, "%s@%s!%s", device->model, device->tenant, device->serial ); + } + else + { + len=strlen(device->model)+strlen(device->serial)+3; + buff = (char *)calloc(len, sizeof(char)); + //buff[len]='\0'; + snprintf(buff,len, "%s!%s", device->model, device->serial); + } + + printDebug(buff); + + return buff; + } + +/**************************************************************************************/ +/*getContentType() */ +/* */ +/*A convenience method to allow different messages to have different media types. The */ +/*media types are set forth in the protocol specification. The function will return a */ +/*a pointer to a declared string, for which you do not need to free. */ +/* */ +/* */ +/* */ +/**************************************************************************************/ + +char *getContentType(char *contentBuff, int type) { + switch(type) { + case 0: + contentBuff=(char *)contentTypes[MIME_JSON]; + break; + default: + contentBuff=(char *)contentTypes[MIME_JSON]; + break; + } + return contentBuff; +} + +char *getGeneralType(char *contentBuff) { + return getContentType(contentBuff, TRANS_TYPE_JSON); + } + +/**************************************************************************************/ +/*int handleResponse() */ +/* */ +/*A catch-all method that will handle any egress messages sent from the platform back */ +/*to the device. If the JSON returned is valid it will dispatch the requests as needed*/ +/* */ +/* */ +/* */ +/**************************************************************************************/ +//Possible returns: +// AX_EGR_JSON_PARSE_FAIL -- A failure to parse the JSON that was returned + +int handleResponse(HTTP_Transmission *response){ + cJSON *resp_int, *temp, *temp_child, *instructions, *instruction_child; + int retVal=AX_OK; + if(response->body==NULL) {return AX_OK;} //if there's no body, there's nothing to do here. + + resp_int=cJSON_Parse(response->body); + if(resp_int==NULL) { + return AX_GEN_PARSE_ERR; + } + printDebug("Creating software packages\n"); + temp=cJSON_GetObjectItem(resp_int, "packages"); + if(temp!=NULL) { + //Handle a software package here + int ctr=0, pkg_ctr2=0; + int sz=cJSON_GetArraySize(temp); + int instructionCt=0; + ax_package *temp_package; + + for(ctr=0; ctr<sz; ctr++) + { + printDebug("Parsing package[]...\n"); + temp_child=cJSON_GetArrayItem(temp, ctr); + //Create an ax_package for this + temp_package=(ax_package *)malloc(sizeof(ax_package)); + char *pkgID=cJSON_GetObjectItem(temp_child, "id")->valuestring; + retVal=ax_pkg_createPackage(temp_package, pkgID, 0, AX_NO_PRIORITY); + temp_package->priority=cJSON_GetObjectItem(temp_child, "priority")->valueint; + temp_package->time=cJSON_GetObjectItem(temp_child, "time")->valueint; + //add Instructions to the package + instructions=cJSON_GetObjectItem(temp_child, "instructions"); + instructionCt=cJSON_GetArraySize(instructions); + for(pkg_ctr2=0; pkg_ctr2<instructionCt; pkg_ctr2++) + { + //int instrType=-1; + printDebug("Parsing instruction\n"); + instruction_child=cJSON_GetArrayItem(instructions, pkg_ctr2); + + if(strcmp("down", cJSON_GetObjectItem(instruction_child, "@type")->valuestring)==0) { + cJSON *id=cJSON_GetObjectItem(instruction_child, "id"); + char *s_id = NULL; + if(id != NULL){ + s_id=id->valuestring; + } + char *s_path = NULL; + //path is optional so we need to make sure it is here before trying to get the valuestring + cJSON *path = cJSON_GetObjectItem(instruction_child, "fp"); + if(path != NULL){ + s_path=path->valuestring; + } + else{ + path = cJSON_GetObjectItem(instruction_child, "path"); + if(path != NULL){ + s_path=path->valuestring; + } + } + char *s_filename = NULL; + cJSON *fn = cJSON_GetObjectItem(instruction_child, "fn"); + if(fn != NULL){ + s_filename=fn->valuestring; + } + else{ + path = cJSON_GetObjectItem(instruction_child, "filename"); + if(path != NULL){ + s_path=path->valuestring; + } + } + retVal=ax_pkg_addDLInstruction(temp_package, s_id, s_path, s_filename); + } + //if it's not a download instruction, we don't care; down was the only one available in AMMP1.0 + } + //Now we tell someone that we've got a software package + scm_download_req(temp_package); + } + } + int dictr1=0; + //Set Data Item Commands will occur here. + temp=NULL; + temp_child=NULL; + instructions=NULL; + instruction_child=NULL; + + printDebug("Setting Data Item Commands\n"); + temp=cJSON_GetObjectItem(resp_int, "set"); + if(temp!=NULL){ + int disz=cJSON_GetArraySize(temp); + for(dictr1=0; dictr1<disz; dictr1++) + { + temp_child=cJSON_GetArrayItem(temp, dictr1); + instructions=cJSON_GetObjectItem(temp_child, "dataItems"); + instruction_child=instructions->child; + while(instruction_child!=NULL){ + if(instruction_child->type==cJSON_String) { + data_item_write(instruction_child->string, instruction_child->valuestring, 0, AX_STRING); + } + else if(instruction_child->type==cJSON_False) { + data_item_write(instruction_child->string, NULL, AX_FALSE, AX_DIGITAL); + } + else if(instruction_child->type==cJSON_True) { + data_item_write(instruction_child->string, NULL, AX_TRUE, AX_DIGITAL); + } + else { + data_item_write(instruction_child->string, NULL, instruction_child->valuedouble, AX_ANALOG); + } + instruction_child=instruction_child->next; + } + + } + } + //Data Item Poll requests here. + printDebug("Setting Data Item Poll requests\n"); + int dictr2=0; + temp=NULL; + temp_child=NULL; + instructions=NULL; + instruction_child=NULL; + temp=cJSON_GetObjectItem(resp_int, "send"); + if(temp!=NULL){ + int dissz=cJSON_GetArraySize(temp); + for(dictr2=0; dictr2<dissz; dictr2++) { + temp_child=cJSON_GetArrayItem(temp, dictr2); + instructions=cJSON_GetObjectItem(temp_child, "dataItems"); + instruction_child=instructions->child; + while(instruction_child!=NULL){ + data_item_request(instruction_child->valuestring); + instruction_child=instruction_child->next; + } + } + } + + cJSON_Delete(resp_int);//dispose of the cJSON object + free(response->body); + + + return retVal; + } + + +