Axeda demo software for u-blox C027 (GSM)

Dependencies:   mbed

AMMP/axDomain.c

Committer:
AxedaCorp
Date:
2014-08-11
Revision:
0:a725e8eab383

File content as of revision 0:a725e8eab383:

/************************************************************************************/
/* axDomain.c                                                                       */
/* �2013 Axeda Corporation                                                          */
/*                                                                                  */
/* Defines methods for creation and interaction with Axeda domain constructs. This  */
/* is a device independent implementation which can be applied to any device that   */
/* supports ANSI C.                                                                 */
/************************************************************************************/
#include "axDomain.h"
#include "string.h"
#include "axSettings.h"
#include <stdlib.h>
#include <stdio.h>



/************************************************************************************/
/* createAlarm()                                                                    */
/*                                                                                  */
/* Stores the supplied values into the structure pointed to by alm.                 */
/*                                                                                  */
/* alm(required) : a pointer to an empty alarm structure                            */
/* name(required) : the name of the alarm                                           */
/* description(required) : a more detailed account of the alarm                     */
/* severity(required) : a numerical value from 0-1000, with 1000 being the highest  */
/* dataItem(optional) : a pointer to a dataItem structure containing the data item  */
/*                      that triggered this alarm. Use NULL for a generic alarm.    */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARG_NULL, AX_GEN_STR_TRUNC, AX_OK     */
/************************************************************************************/
int ax_data_createAlarm(ax_alarm *alm, char *alName, char *alDescription, int alSeverity, char *cause, char *reason, int timeOccured, int priority)
  {
  int retVal=AX_OK;
  if((alSeverity <0)||(alSeverity>1000))
    {
    return AX_OUT_OF_RANGE;
    }
  if((!alm)||(!alName)||(!alDescription))
    {
    return AX_ARGNULL;
    }
  if(strlen(alName)<=0) {
    return AX_ARGNULL;
    }

  snprintf(alm->alarmName, AX_ALM_NAME_S, alName);
  if(strlen(alName)>AX_ALM_NAME_S){
      retVal=AX_GEN_STR_TRUNC;
      }

  snprintf(alm->alarmDescription, AX_ALM_DESC_S, alDescription);
  if(strlen(alDescription)> AX_ALM_DESC_S) {
      retVal=AX_GEN_STR_TRUNC;
      }

  snprintf(alm->alarmCause, AX_ALM_CAUSE_S, cause);
  if(strlen(cause)>AX_ALM_CAUSE_S) {
     retVal=AX_GEN_STR_TRUNC;
     }

  snprintf(alm->alarmReason, AX_ALM_REAS_S, reason);
  if(strlen(reason)>AX_ALM_REAS_S){
     retVal=AX_GEN_STR_TRUNC;
     }

  alm->alarmSeverity=alSeverity;
  alm->dateAcquired=timeOccured;
  alm->priority=priority;
  
  return retVal;
  }

/*************************************************************************************/
/* createDataItem()                                                                  */
/*                                                                                   */
/* This function will store information about a dataItem into a structure supplied   */
/* by the calling method. There are traditionally 3 types of data Items, analog,     */
/* string and digital.                                                               */
/*                                                                                   */
/* destDI(required) : A pointer to the structure where the data will be stored       */
/* diName(required) : A character array containing the name of the data item         */
/* diType(required) : A integer value indicating the data Item type. Can be          */
/*                    AX_STRING, AX_DIGITAL, AX_ANALOG                               */
/* stringValue(optional): If the type is AX_STRING, this value MUST be populated or  */
/*                        an error will be returned. This is the value of the        */
/*                        dataItem. If it is a String use zero for the numericValue  */
/* numericValue(optional): If the type is AX_ANALOG or AX_DIGITAL this value MUST be */
/*                         provided or an error will be returned. For AX_ANALOG di's */
/*                         this value can be any numeric value within language       */
/*                         constraints. For AX_DIGITAL, this value must be 1 or 0.   */
/*                         1 will be considered true and 0 will be considered false. */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK       */
/*                        AX_DI_UNKNOWN_TYPE, AX_UNKNOWN                             */
/************************************************************************************/
int ax_data_createDataItem(ax_dataSet *destDI, char *diName, int diType, char *stringValue, double numericValue, int timeAcquired, int priority) {
  int retVal=AX_UNKNOWN;
  if(!destDI) { return AX_ARGNULL; }
  if(!diName) {return AX_ARGNULL; }
  if((diType>3)&&(diType<1)) {return AX_ARGNULL; }
  if(timeAcquired<0) {return AX_OUT_OF_RANGE; }
  if((priority<-1)||(priority>100)) { return AX_OUT_OF_RANGE; }
  if(destDI->created!=AX_TRUE) {
      retVal=ax_data_createSet(destDI, timeAcquired, priority);
      if(retVal!=AX_OK) { return retVal; }
      }
  
  retVal=ax_data_addToSet(destDI, diName, diType, stringValue, numericValue);
  
  return retVal;
  }
/*************************************************************************************/
/* createAnalogDataItem()                                                            */
/*                                                                                   */
/* This function will store information about a dataItem into a structure supplied   */
/* by the calling method. This is a special case of the ax_data_createDataItem() call*/
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK       */
/*                        AX_DI_UNKNOWN_TYPE, AX_UNKNOWN                             */
/*************************************************************************************/
int ax_data_createAnalogDataItem(ax_dataSet *destDI, char *diName, double value, int timeAcquired, int priority) {
  return ax_data_createDataItem(destDI, diName, AX_ANALOG, NULL, value, timeAcquired, priority);
  }

/*************************************************************************************/
/* createDigitalDataItem()                                                           */
/*                                                                                   */
/* This function will store information about a dataItem into a structure supplied   */
/* by the calling method. There are traditionally 3 types of data Items, analog,     */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK       */
/*                        AX_DI_UNKNOWN_TYPE, AX_UNKNOWN                             */
/*************************************************************************************/
int ax_data_createDigitalDataItem(ax_dataSet *destDI, char *diName, double value, int timeAcquired, int priority) {
  return ax_data_createDataItem(destDI, diName, AX_DIGITAL, NULL, value, timeAcquired, priority);
  }

/*************************************************************************************/
/* createDataItem()                                                                  */
/*                                                                                   */
/* This function will store information about a dataItem into a structure supplied   */
/* by the calling method. There are traditionally 3 types of data Items, analog,     */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK       */
/*                        AX_DI_UNKNOWN_TYPE, AX_UNKNOWN                             */
/*************************************************************************************/
int ax_data_createStringDataItem(ax_dataSet *destDI, char *diName, char *value, int timeAcquired, int priority) {
  return ax_data_createDataItem(destDI, diName, AX_STRING, value, -1, timeAcquired, priority);
  }

/************************************************************************************/
/*ax_data_createSet()                                                               */
/*                                                                                  */
/*Creates and populates a dataSet struct pointed to by the *set parameter. A dataSet*/
/*can have multiple data items added by the ax_data_addToSet() method.              */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK      */
/************************************************************************************/
int ax_data_createSet(ax_dataSet *set, int acquisitionTime, int priority) {

  if(!set) { return AX_ARGNULL; }
  if((priority<-1)||(priority>100)) { return AX_OUT_OF_RANGE; }
  if(acquisitionTime<0) {return AX_OUT_OF_RANGE;  }
    set->dataNode_ct=0;
    set->data_first=NULL;
    set->data_last=NULL;

    if(acquisitionTime >=0) {
        set->acquisitionTime=acquisitionTime;
        }
    else {
        set->acquisitionTime=-1;
    }
    if((priority >=1)&&(priority<=100)) {
        set->priority=priority;
        }
    else {
        set->priority=AX_NO_PRIORITY;
        }

    set->created=AX_TRUE;
    return AX_OK;
    }
/************************************************************************************/
/*ax_data_addToSet()                                                                */
/*                                                                                  */
/*Adds data to a preExisting data set. Data is represented as a linked list and     */
/*pointed to by a dataSet structure. Adding data to with this method will cause the */
/*memory to be malloc'd for each data item you set. To remove all data correctly use*/
/*the ax_data_destroySet() function call. You will get memory leaks if you do not.  */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK      */
/*                        AX_DI_UNKNOWN_TYPE                                        */
/************************************************************************************/
int ax_data_addToSet(ax_dataSet *set, char *diName, int diType, char *stringValue, double numericValue){
    ax_dataNode *newNode, *temp=NULL;
    int retVal=AX_UNKNOWN;

    if((diType<1)||(diType>3)){
            return AX_DI_UNKNOWN_TYPE;
            }

      if((!set)||(!diName)){
          return AX_ARGNULL;
            }

      if((diType==AX_STRING)&&(!stringValue)){
          return AX_ARGNULL;
           }
      if((diType==AX_DIGITAL)&&((numericValue<0)||(numericValue>1))){
        return AX_OUT_OF_RANGE;
        }
    //if you didn't create the data set with the function this will make sure the linked list values are set. It MAY overwrite the time and priority if they are already set.
    if(set->created!=AX_TRUE) { ax_data_createSet(set, 0, AX_NO_PRIORITY); }  

    newNode=(ax_dataNode*)malloc(sizeof(ax_dataNode));

    retVal=AX_OK;
    snprintf(newNode->name, AX_DN_NAME_S, diName);
    if(strlen(diName)>AX_DN_NAME_S) {
        retVal=AX_GEN_STR_TRUNC;
        }

    newNode->next=NULL;
    newNode->type=diType;
    if(diType==AX_STRING) {
	snprintf(newNode->sValue, AX_DN_SV_S, stringValue);
        if(strlen(stringValue)>AX_DN_SV_S) {
            retVal=AX_GEN_STR_TRUNC; // if the requested value was too large, set a warning to let us know it was truncated
            }
        }
    else {
        newNode->dValue=numericValue;
        }

    if(set->data_first==NULL) {
        set->data_first=newNode;
        }

    if(set->data_last!=NULL) {
        temp=set->data_last;
        temp->next=(ax_dataNode *)newNode;
        }


    set->data_last=newNode;
    int nodect=set->dataNode_ct;
    nodect++;
    set->dataNode_ct=nodect;

    return retVal;
    }
/************************************************************************************/
/*ax_data_addStringToSet()                                                          */
/*                                                                                  */
/*Adds data to a preExisting data set. Data is represented as a linked list and     */
/*pointed to by a dataSet structure. Adding data to with this method will cause the */
/*memory to be malloc'd for each data item you set. To remove all data correctly use*/
/*the ax_data_destroySet() function call. You will get memory leaks if you do not.  */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK      */
/************************************************************************************/
int ax_data_addStringToSet(ax_dataSet *set, char *diName, char *value) {
   return ax_data_addToSet(set, diName, AX_STRING, value, -1);
}
/************************************************************************************/
/*ax_data_addAnalogToSet()                                                          */
/*                                                                                  */
/*Adds data to a preExisting data set. Data is represented as a linked list and     */
/*pointed to by a dataSet structure. Adding data to with this method will cause the */
/*memory to be malloc'd for each data item you set. To remove all data correctly use*/
/*the ax_data_destroySet() function call. You will get memory leaks if you do not.  */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_OK                        */
/************************************************************************************/
int ax_data_addAnalogToSet(ax_dataSet *set, char *diName, double value){
  return ax_data_addToSet(set, diName, AX_ANALOG, NULL, value);
}
/************************************************************************************/
/*ax_data_addDigitalToSet()                                                         */
/*                                                                                  */
/*Adds data to a preExisting data set. Data is represented as a linked list and     */
/*pointed to by a dataSet structure. Adding data to with this method will cause the */
/*memory to be malloc'd for each data item you set. To remove all data correctly use*/
/*the ax_data_destroySet() function call. You will get memory leaks if you do not.  */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_OK                        */
/************************************************************************************/
int ax_data_addDigitalToSet(ax_dataSet *set, char *diName, double value) {
  return ax_data_addToSet(set, diName, AX_DIGITAL, NULL, value);
  }    
    
    
/************************************************************************************/
/*ax_data_destroySet()                                                              */
/*                                                                                  */
/*Iterates through all data items in a dataset and frees them. This assumes all nodes*/
/*have been allocated by malloc.If the addToSet() function was being used then that */
/*will be true.                                                                     */
/*Possible Return Codes: AX_OK  AX_ARGNULL                                          */
/************************************************************************************/
int ax_data_destroySet(ax_dataSet *set) {

    if(set!=NULL) {
    ax_dataNode *curr=set->data_first, *next;
    int ctr;
    for(ctr=0; ctr<set->dataNode_ct; ctr++)
        {
        next=(ax_dataNode *)curr->next;
        free(curr);
        curr=next;
        next=NULL; // CYA'ing here
        }
    set->data_first=NULL;
    set->data_last=NULL;
    }
    else {
	return AX_ARGNULL;
	}

    return AX_OK;
    }


/*************************************************************************************/
/* createEvent()                                                                     */
/*                                                                                   */
/* This function will populate an event structure and check the values to ensure they*/
/* are within protocol limit                                                         */
/* Possible Return Codes: AX_ARGNULL, AX_GEN_STR_TRUNC                               */
/************************************************************************************/
int ax_data_createEvent(ax_event *evt, char *name, char *description, int timeOccured, int priority)
  {
  int retVal=AX_OK;
  if((!evt)||(!name)||(!description)){
    return AX_ARGNULL;
    }
  if((priority<-1)||(priority>100)) {return AX_OUT_OF_RANGE; }

  snprintf(evt->name,AX_EVT_NAME_S, name);
  if(strlen(name)>AX_EVT_NAME_S) {
      retVal= AX_GEN_STR_TRUNC;
      }
 
  snprintf(evt->description, AX_EVT_DESC_S, description);
  if(strlen(description)>AX_EVT_DESC_S) {
      retVal=AX_GEN_STR_TRUNC;
      }

  evt->dateAcquired=timeOccured;
  evt->priority=priority;
  return retVal;
  }
  



/************************************************************************************/
/* createLocation()                                                                 */
/*                                                                                  */
/* This function will populate a location structure storing the current location    */
/*                                                                                  */
/* loc (required) : A structure that will be populated with the data                */
/* lat (required) : A number between 90 and -90 representing the degrees latitude.  */
/* lon (required) : A number between 180 and -180 representing the degrees longitude*/
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARGNULL, AX_OK                        */
/************************************************************************************/
int ax_data_createLocation(ax_location *loc, double lat, double lon, double alt, int timeAcquired, int priority){
  if(!loc){
    return AX_ARGNULL;
    }
  
  if((lat>90)||(lat<-90)){
    return AX_OUT_OF_RANGE;
    }
  
  if((lon>180)||(lon<-180)){
    return AX_OUT_OF_RANGE;
    }
  
  
  loc->latitude=lat;  
  loc->longitude=lon;
  loc->altitude=alt;

  loc->dateAcquired=timeAcquired;
  loc->priority=priority;
  return AX_OK;
  }

/************************************************************************************/
/* createModelSerialDeviceId()                                                      */
/*                                                                                  */
/* This function will populate a structure that stores data about the device's iden-*/
/* tification. The Axeda platform allows for multiple ways of identifying a device. */
/*                                                                                  */
/* device(required) : a pointer to a structure where the data will be stored        */
/* model (required) : A model number that describes a particular family of device.  */
/*                    If this were describing a car it could be a Ford_Mustang      */
/* serial (required) : A unique Identifier for the device. If it was a car it would */
/*                    be analagous to the VIN number.                               */
/* tenant (optional) : The identifier of the Axeda tenant instance. Not currently   */
/*                      used and should always default to zero.                     */
/* Possible Return Codes: AX_ARGNULL, AX_GEN_STR_TRUNC, AX_OK                       */
/************************************************************************************/

int ax_data_createModelSerialDeviceId(ax_deviceID *device, char *model, char *serial, char *tenant) {
  int retVal=AX_OK;
    if((!device)||(!model)||(!serial)){
    return AX_ARGNULL;
    }
  snprintf(device->model, AX_MSID_MDL_S, model);
  if(strlen(model)> AX_MSID_MDL_S) {
      retVal=AX_GEN_STR_TRUNC;
      }

  snprintf(device->serial, AX_MSID_SER_S, serial);
  if(strlen(serial)>AX_MSID_SER_S) {
      retVal=AX_GEN_STR_TRUNC;
      }

  memset(device->tenant, '\0', AX_MSID_TEN_S);
  if(tenant!=NULL) {
  	snprintf(device->tenant, AX_MSID_TEN_S, "%s", tenant);
  	if(strlen(tenant)>AX_MSID_TEN_S) { retVal=AX_GEN_STR_TRUNC; }
      	}

  return retVal;
  }
/************************************************************************************/
/*ax_createPlatform()                                                               */
/*                                                                                  */
/*Populates the ax_platform struct pointed to by axedaCloud It will add the hostname*/
/*ip and port. Other parts of the ax_platform structure can be populated at will    */
/*                                                                                  */
/*                                                                                  */
/* Possible Return Codes: AX_OUT_OF_RANGE, AX_ARG_NULL, AX_GEN_STR_TRUNC, AX_OK     */
/************************************************************************************/
int ax_createPlatform(ax_platform *axedaCloud, const char *hostname, int ip[], int port)
  {
  int retVal=AX_OK;
//Check that there's an IP or Hostname.
  if((!ip)&&(!hostname))
    { return AX_ARGNULL; } 
  if(!axedaCloud) {return AX_ARGNULL; }
//Check the port is in bounds of known ports
  if((port<0)||(port>65536)) {
	return AX_OUT_OF_RANGE;
	}
  if((hostname)&&(strlen(hostname)>0))
    {
    snprintf(axedaCloud->hostname, AX_PLAT_HOST_S, hostname);
    if(strlen(hostname)>AX_PLAT_HOST_S) {
        retVal=AX_GEN_STR_TRUNC;
        }
    }
   else {
    return AX_ARG_EMPTY;
    }

 if(ip)
    {
     int i=0;
    for(i=0; i<4; i++) { if((ip[i]>255)||(ip[i]<0)) return AX_OUT_OF_RANGE; }
    axedaCloud->ip[0]=ip[0];
    axedaCloud->ip[1]=ip[1];
    axedaCloud->ip[2]=ip[2];
    axedaCloud->ip[3]=ip[3];

    }
  axedaCloud->port=port;
  return retVal;
  }
/************************************************************************************/
/* ax_createFile()                                                                  */
/*                                                                                  */
/* Populates a file structure with the necessary info and checks the arguments to   */
/* ensure compliance with the protocol                                              */
/* Possible Return Codes: AX_UNKNOWN, AX_GEN_STR_TRUNC, AX_OK, AX_ARGNULL           */
/*                                                                                  */
/*file (required): A pointer to an already existing ax_file structure to store data */
/*name (required): A name for the file, this can be any arbitrary string. It will   */
/*                 appear on the platform after upload                              */
/*hint (optional): A string that allows for easy retrieval on the platform          */
/*size (required): The size of the file to send. The end of the file would occur at */
/*                 data+size                                                       */
/*data (required): A pointer to the starting address of data to send, it can be the */
/*                 first cell in an array or any location in memory.                */
/************************************************************************************/
int ax_createFile(ax_file *file, char *name, char *hint, int size, unsigned char *data)
    {
    int retVal=AX_OK;
//ARG Checks
    if(size<=0) { return AX_OUT_OF_RANGE; }
	if(file==NULL) { return AX_ARGNULL; }
	if(name==NULL) { return AX_ARGNULL; }
	if(data==NULL) { return AX_ARGNULL; }
//Store the data into the structure
    snprintf(file->name, AX_FILE_NAME_S, name);
    if(strlen(name)>AX_FILE_NAME_S){
        retVal=AX_GEN_STR_TRUNC;
        }

    if(hint!=NULL) {
	    snprintf(file->hint, AX_FILE_HINT_S, hint);
	    if(strlen(hint)>AX_FILE_HINT_S) {
	        retVal=AX_GEN_STR_TRUNC;
	        }
	}

    file->size=size;
    file->data=data;

    return retVal;
    }

/************************************************************************************/
/*ax_createPackageInstruction()                                                     */
/*                                                                                  */
/*populates an ax_package_instruction structre passed in. This should never need to */
/*be called by a library implementor. It will only be used for egress notifications */
/*                                                                                  */
/*                                                                                  */
/************************************************************************************/
int ax_pkg_createPackageInstruction(ax_package_instruction *inst, int instruction_type, char *file_id, char *path, char *filename){
	int retVal=AX_OK;

	inst->instruction_type=instruction_type;
	int fdSZ=snprintf(inst->file_id, AX_PKGI_FID_S, file_id);
	if(strlen(file_id)>fdSZ) {
       retVal=AX_GEN_STR_TRUNC;
                      }
                  
    int pathSZ=snprintf(inst->path, AX_PKGI_PATH_S, path);
	if(strlen(path)>pathSZ) {
       retVal=AX_GEN_STR_TRUNC;
       }

                  
    int fnSZ=snprintf(inst->filename, AX_PKGI_FNAME_S, filename);
	if(strlen(filename)>fnSZ) {
       retVal=AX_GEN_STR_TRUNC;
       }
	inst->next=NULL;

  return retVal;
  }

/************************************************************************************/
/*ax_createPackage()                                                                */
/*                                                                                  */
/*populates an ax_package structre passed in. This should never need to be called by*/ 
/*a library implementor. It will only be used for egress notifications              */
/*                                                                                  */
/*                                                                                  */
/************************************************************************************/
int ax_pkg_createPackage(ax_package *package, char *pkgID, int time, int priority) {
  int retVal=AX_OK;

  int nmsz=snprintf(package->packageID, AX_PKG_ID_S, pkgID);
  if(strlen(pkgID)> nmsz) {
    retVal=AX_GEN_STR_TRUNC;
	}
  package->time=time;
  package->priority=priority;
  package->instructions=NULL;
  

return retVal;
} 
/************************************************************************************/
/*ax_pkg_addDLInstruction()                                                          */
/*                                                                                   */
/*Adds a file download package to an already existing package. This function will    */ 
/*dynamically allocate memory for each instruction. That memory will need to be freed*/
/*When the status is complete                                                        */
/*                                                                                   */
/************************************************************************************/
int ax_pkg_addDLInstruction(ax_package *pkg, char *file_id, char *path, char *filename) {
  int retVal=AX_UNKNOWN;
  ax_package_instruction *curr=NULL;
  ax_package_instruction *newInst=NULL;

  newInst=(ax_package_instruction *)calloc(1, sizeof(ax_package_instruction));
  retVal=ax_pkg_createPackageInstruction(newInst, AX_PKG_DOWNLOAD, file_id, path, filename);

  if(pkg->instructions!=NULL) {
	curr=pkg->instructions;
	//Go to the end of the list
  	while(curr->next!=NULL) {
		curr=curr->next;
		}
	curr->next=newInst;
 	}

  else {
	pkg->instructions=newInst;
	}  


return retVal;
}
/*************************************************************************************/
/*ax_pkg_destroyPackage()                                                            */
/*                                                                                   */
/*Free's lined package Instructions when created by the ax_pkg_add*() function. Be   */
/*careful not to use this on a package with instructions that were manually declared */
/*This does not attempt to free the package itself as it may have been declared and  */
/*not dynamically allocated.                                                         */
/************************************************************************************/
int ax_pkg_destroyPackage(ax_package *pkg) {
  ax_package_instruction *curr=NULL;
  ax_package_instruction *target=NULL;
  curr=pkg->instructions;
  while(curr!=NULL) {
	target=curr;       //We'll aim at the current node   
	curr=curr->next;   //store the value for the next node
    free(target);	   //kill the target node
   }
return AX_OK;
}