Yalgaar mBed SDK for real-time messaging

Dependents:   YalgaarSDK

Fork of MQTT by Joerg Wende

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers yalgaar_api.cpp Source File

yalgaar_api.cpp

00001 /** @fileName <yalgaar_api>
00002  *  @brief - <Yalgaar SDK APIS>
00003  *
00004  *  @Version:V:01:00:000
00005  *
00006  *
00007  * @Copyright:
00008  * Copyright (c) 2010 System Level Solution (India) pvt.ltd. Corporation.  All rights reserved.
00009  *
00010  * License: Free License for Yalgaar Users
00011  * Disclaimer:
00012  * SLS MAKES NO REPRESENTATION, WARRANTY, OR CONDITION OF ANY KIND, EXPRESS,
00013  * IMPLIED, STATUTORY, OR OTHERWISE OR IN ANY COMMUNICATION WITH YOU, INCLUDING,
00014  * BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY
00015  * QUALITY, FITNESS FOR ANY PARTICULAR PURPOSE, NONINFRINGEMENT, AND THEIR
00016  * EQUIVALENTS.
00017  */
00018 #include "yalgaar_api.h"
00019 
00020 Serial pc2(USBTX, USBRX, 115200);
00021 
00022 void (* connection_main_Callback)(char *);
00023 void (* yalgaar_presence_message_recv)(char *);
00024 void (* yalgaar_error_message)(char *error);
00025 void (* yalgaar_new_message)(char * message);
00026 void parse_subscribe_message(char*,char*, unsigned int);
00027 void subscribe_callback_handler(char*,char*, unsigned int);
00028 
00029 char uuid_general[YALGAAR_MAX_UUID_STR_COUNT];
00030 char gclient_key[YALGAAR_CLIENT_KEY_MAX_LENGTH];
00031 
00032 const char *YALGAAR_ERROR_LIST[]= {
00033     "ClientId should not be null.",
00034     "Invalid ClientId.",
00035     "Invalid ClientKey.ClientKey is not registered. ",
00036     "Invalid Uuid.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
00037     "ClientKey is not active.",
00038     "SSL is not enable.",
00039     "The maximum connection limit has been reached.",
00040     "Invalid subscribe channel.",
00041     "Invalid subscribe channel.ClientKey does not match.",
00042     "Multiple subscribe channels are not allowed. Multiplexing is not enable.",
00043     "Invalid subscribe channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
00044     "Storage is not enable.",
00045     "Presence is not enable.",
00046     "Entered history channel has not been subscribed.",
00047     "Message can not be null.",
00048     "Invalid publish channel.",
00049     "Invalid publish channel.ClientKey does not match.",
00050     "Message count exceeds maximum limit.",
00051     "Message size exceeds maximum limit.",
00052     "Invalid publish channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
00053     "Invalid UnSubscribe channel.",
00054     "Invalid UnSubscribe channel.ClientKey does not match.",
00055     "Invalid UnSubscribe channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50."
00056 };
00057 
00058 /**********************************************************************************
00059  *   @name                      : yalgaar_error_t yalgaar_wrapper_validate_string(const char * str)
00060  *   @param const char * str    : char pointer str parameter contains string which have to validate.
00061  *   @return yalgaar_error_t                : function returns error id.
00062  *   @brief                     : validate the uuid for proper alpha numeric value(as per defined).
00063  **********************************************************************************/
00064 Yalgaar_Error_t yalgaar_wrapper_validate_string(const char * str)
00065 {
00066     char a = strlen(str);
00067     int i = 0;
00068 
00069     if(a > YALGAAR_MAX_CHANNEL_NAME_LENGTH) {
00070         return INVL_STRING;
00071     }
00072     for(i=0; i<a; i++) {
00073         if (0x3f < str[i]) {
00074             if(str[i] < 0x5b) {
00075                 continue;
00076             }
00077         }
00078         if(0x30 <=str[i]) {
00079             if(str[i] <= 0x39) {
00080                 continue;
00081             }
00082         }
00083         if(0x61 <=str[i]) {
00084             if(str[i] <= 0x7a) {
00085                 continue;
00086             }
00087         }
00088         if(str[i] == 0x5f) {
00089             continue;
00090         }
00091         if(str[i] == 0x2d) {
00092             continue;
00093         }
00094         return INVL_STRING;
00095     }
00096 
00097     return SUCCESS;
00098 }
00099 /**********************************************************************************
00100  *   @name                  : static char *rand_string(char *str, size_t size)
00101  *   @param  char *str      : str is used to store generated random string for UUID.
00102  *   @param size_t size : size is used into string generation for random string length.
00103  *   @return void           :
00104  *   @brief                 : generate random string for dynamic UUID for topic string creation.
00105  **********************************************************************************/
00106 void rand_string(char *str, size_t size)
00107 {
00108     const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
00109     if (size) {
00110         size_t n;
00111         --size;
00112         for (n = 0; n < size; n++) {
00113             int key = rand() % (int) (sizeof charset - 1);
00114             str[n] = charset[key];
00115         }
00116         str[size] = '\0';
00117     }
00118 }
00119 /**********************************************************************************
00120 *   @name                  : char* rand_string_alloc(size_t size)
00121 *   @param size_t size     : size parameter is used to malloc size for random string.
00122 *   @return char *         : returns generaed random string pointer.
00123 *   @brief                 : memory allocate for variable to store rand string.
00124 **********************************************************************************/
00125 char* rand_string_alloc(size_t size)
00126 {
00127     char *s = (char *)malloc(size + 1);
00128     if (s) {
00129         rand_string(s, size);
00130     }
00131     return s;
00132 }
00133 
00134 /**********************************************************************************
00135  *   @name                  : void enum_to_message(yalgaar_error_t *error_msg,unsigned char *errorString)
00136  *   @param  error_msg      : error_msg is int parameter for error message enum.
00137  *   @param  errorString    : errorString is char pointer, error string copy from YALGAAR_ERROR_LIST & stored into errorString
00138  *   @return void           :
00139  *   @brief                 : convert error Id(enum) to error message and set into char pointer.
00140  **********************************************************************************/
00141 void yalgaar::enum_to_message(int error_msg,char *errorString)
00142 {
00143     if(error_msg==CLIENT_NULL) {
00144         strncpy(errorString,YALGAAR_ERROR_LIST[0],YALGAAR_ERROR_MESSAGE_LENGTH);
00145     } else if(error_msg==CLIENT_NOT_VALID) {
00146         strncpy(errorString,YALGAAR_ERROR_LIST[1],YALGAAR_ERROR_MESSAGE_LENGTH);
00147     } else if(error_msg==CLIENT_KEY_NOT_REG) {
00148         strncpy(errorString,YALGAAR_ERROR_LIST[2],YALGAAR_ERROR_MESSAGE_LENGTH);
00149     } else if(error_msg==UUID_NOT_VALID) {
00150         strncpy(errorString,YALGAAR_ERROR_LIST[3],YALGAAR_ERROR_MESSAGE_LENGTH);
00151     } else if(error_msg==CLIENT_KEY_NOT_ACTIVE) {
00152         strncpy(errorString,YALGAAR_ERROR_LIST[4],YALGAAR_ERROR_MESSAGE_LENGTH);
00153     } else if(error_msg==SSL_NOT_ENABLE) {
00154         strncpy(errorString,YALGAAR_ERROR_LIST[5],YALGAAR_ERROR_MESSAGE_LENGTH);
00155     } else if(error_msg==CONNECTION_LIMIT_EXCEED) {
00156         strncpy(errorString,YALGAAR_ERROR_LIST[6],YALGAAR_ERROR_MESSAGE_LENGTH);
00157     } else if(error_msg==SUBCRIPTION_NOT_VALID) {
00158         strncpy(errorString,YALGAAR_ERROR_LIST[7],YALGAAR_ERROR_MESSAGE_LENGTH);
00159     } else if(error_msg==SUBCRIPTION_CLIENT_KEY_NOT_MATCH) {
00160         strncpy(errorString,YALGAAR_ERROR_LIST[8],YALGAAR_ERROR_MESSAGE_LENGTH);
00161     } else if(error_msg==MULTIPLE_SUBCRIBES_NOT_ALLOWED) {
00162         strncpy(errorString,YALGAAR_ERROR_LIST[9],YALGAAR_ERROR_MESSAGE_LENGTH);
00163     } else if(error_msg==SUBCRIBE_CHANNEL_LENGTH_EXCEED) {
00164         strncpy(errorString,YALGAAR_ERROR_LIST[10],YALGAAR_ERROR_MESSAGE_LENGTH);
00165     } else if(error_msg==STORAGE_NOT_ENABLE) {
00166         strncpy(errorString,YALGAAR_ERROR_LIST[11],YALGAAR_ERROR_MESSAGE_LENGTH);
00167     } else if(error_msg==PRESENCE_NOT_ENABLE) {
00168         strncpy(errorString,YALGAAR_ERROR_LIST[12],YALGAAR_ERROR_MESSAGE_LENGTH);
00169     } else if(error_msg==HISTORY_CHANNEL_NOT_SUBCRIBE) {
00170         strncpy(errorString,YALGAAR_ERROR_LIST[13],YALGAAR_ERROR_MESSAGE_LENGTH);
00171     } else if(error_msg==MESSAGE_NOT_NULL) {
00172         strncpy(errorString,YALGAAR_ERROR_LIST[14],YALGAAR_ERROR_MESSAGE_LENGTH);
00173     } else if(error_msg==PUBLISH_CHANNEL_NOT_VALID) {
00174         strncpy(errorString,YALGAAR_ERROR_LIST[15],YALGAAR_ERROR_MESSAGE_LENGTH);
00175     } else if(error_msg==PUBLISH_CLIENT_KEY_NOT_MATCH) {
00176         strncpy(errorString,YALGAAR_ERROR_LIST[16],YALGAAR_ERROR_MESSAGE_LENGTH);
00177     } else if(error_msg==MESSAGE_CNT_EXCEED) {
00178         strncpy(errorString,YALGAAR_ERROR_LIST[17],YALGAAR_ERROR_MESSAGE_LENGTH);
00179     } else if(error_msg==MESSAGE_SIZE_EXCEED) {
00180         strncpy(errorString,YALGAAR_ERROR_LIST[18],YALGAAR_ERROR_MESSAGE_LENGTH);
00181     } else if(error_msg==MESSAGE_LENGTH_EXCEED) {
00182         strncpy(errorString,YALGAAR_ERROR_LIST[19],YALGAAR_ERROR_MESSAGE_LENGTH);
00183     } else if(error_msg==UNSUBSCRIBE_CHANNEL_NOT_VALID) {
00184         strncpy(errorString,YALGAAR_ERROR_LIST[20],YALGAAR_ERROR_MESSAGE_LENGTH);
00185     } else if(error_msg==UNSUBSCRIBE_CLIENT_KEY_NOT_MATCH) {
00186         strncpy(errorString,YALGAAR_ERROR_LIST[21],YALGAAR_ERROR_MESSAGE_LENGTH);
00187     } else if(error_msg==UNSUBSCRIBE_CHANNEL_LENGTH_EXCEED) {
00188         strncpy(errorString,YALGAAR_ERROR_LIST[22],YALGAAR_ERROR_MESSAGE_LENGTH);
00189     } else {
00190         strcpy(errorString,"Undefined Error");
00191     }
00192     return;
00193 }
00194 /**********************************************************************************
00195  *   @name                      : void parse_subscribe_message(char* topic, char* payload, unsigned int length)
00196  *   @param char * topic        : topicName parameter have received message topic name.
00197  *   @param unsigned int length : payload_len parameter have Received message payload length.
00198  *   @param uint8_t* payload    : payload * have row data of received message for parsing
00199  *   @return void               : .
00200  *   @brief                     : filter message using subscribe message for specific message.
00201  **********************************************************************************/
00202 void parse_subscribe_message(char* topic, char* payload, unsigned int length)
00203 {
00204     char temppayload[length];
00205     char * start_string =NULL;
00206     memset(temppayload,0,length);
00207     for (int i=0; i<length; i++) {
00208         temppayload[i] = payload[i];
00209     }
00210     start_string = strstr(temppayload,"isPresence");
00211     if(start_string != NULL) {
00212         yalgaar_presence_message_recv(payload);
00213     } else {
00214         yalgaar_new_message(payload);
00215     }
00216 
00217 }
00218 /**********************************************************************************
00219  *   @name                                  : void subscribe_callback_handler(char* topic, char* payload, unsigned int length)
00220  *   @param char* topic                     : subscribe topic for yalgaar
00221  *   @param uint8_t* payload                : Payload of recieve message
00222  *   @param unsigned int length             : length of recieve mesaage
00223  *   @return void                           :
00224  *   @brief                                 : this function will called when any message received on specific subscribed topic.
00225  **********************************************************************************/
00226 void subscribe_callback_handler(char* topic, char* payload, unsigned int length)
00227 {
00228     parse_subscribe_message(topic,payload,length);
00229 }
00230 
00231 /**********************************************************************************
00232  *   @name                                          : Yalgaar_Error_t yalgaar::yalgaar_connect(const char* id,void(*connectionCallback)( int,char * ))
00233  *   @param char *clientKey                         : clientkey contains the yalgaar server clientKey for all SDK.
00234  *   @param void(*connectionCallback)( int,char* )  : connectionCallback is a function pointer of connect callback function.
00235  *   @return Yalgaar_Error_t                        : contains the success or failure status of connection.
00236  *   @brief                                         : This function is called before any other function of this SDK for init the mosquitto library and it will get connected to the yalgaar server.
00237  **********************************************************************************/
00238 Yalgaar_Error_t yalgaar::yalgaar_connect(const char* clientKey,const char *uuid,void(*connectionCallback)(char * ))
00239 {
00240     char clientID[YALGAAR_CLIENT_DEFAULT_STRING_LEN];
00241     bool ret;
00242 
00243     //UUID Validation
00244     if(clientKey == NULL || clientKey == "") {
00245         return CLIENT_NULL;
00246     }
00247     if(uuid == NULL || uuid == "") {
00248         uuid = rand_string_alloc(YALGAAR_MAX_UUID_STR_COUNT);
00249         strncpy(uuid_general,uuid,sizeof(uuid_general));
00250     } else {
00251         if(yalgaar_wrapper_validate_string(uuid) != SUCCESS) {
00252             return UUID_NOT_VALID;
00253         }
00254 
00255         strncpy(uuid_general,uuid,sizeof(uuid_general));
00256     }
00257     sprintf(clientID,"%s/%s",clientKey,uuid_general);
00258     connection_main_Callback=connectionCallback;
00259     snprintf(gclient_key,sizeof(gclient_key),"%s",(char *)clientKey);
00260     ret=connect(clientID);
00261         wait(5.0f); 
00262     connection_state(ret);
00263     if (ret == 1)
00264         return SUCCESS;
00265     else
00266         return FAILURE;
00267 }
00268 
00269 /**********************************************************************************
00270  *   @name                      : Yalgaar_Error_t yalgaar_publish(const char *topic,char *payload)
00271  *   @param const char *topic   : channel name to publish on specific topic
00272  *   @param char *payload       : message string to publish
00273  *   @return Yalgaar_Error_t    : it will return success or failure status of publish message.
00274  *   @brief                     : this function is called to publish any message to specific topic.
00275  **********************************************************************************/
00276 Yalgaar_Error_t yalgaar::yalgaar_publish(const char* topic, char* payload)
00277 {
00278     char publish_channel[128]= {0};
00279     if(topic == NULL || topic == "") {
00280         return MESSAGE_LENGTH_EXCEED;
00281     }
00282     if(yalgaar_wrapper_validate_string(topic) != SUCCESS) {
00283         return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
00284     } else {
00285         if(payload=="" || payload==NULL) {
00286             return MESSAGE_NOT_NULL;
00287         }
00288     }
00289     sprintf(publish_channel,"%s/%s",gclient_key,topic);
00290     if(publish(publish_channel,payload) == SUCCESS) {
00291         return SUCCESS;
00292     } else {
00293         return FAILURE;
00294     }
00295 }
00296 /**********************************************************************************
00297  *   @name                                                      : Yalgaar_Error_t yalgaar::yalgaar_subscribe(char * subscribe_channel,void(* sub_mesg_callback)(void *),void(*presence_mesg_callback)(void *), void(*error_msg_callback)(void *))
00298  *   @param char * subscribe_channel                            : topic name of subscription
00299  *   @param void(* sub_mesg_callback)(void *)                   : function pointer of normal message receive callback function
00300  *   @param void(*presence_mesg_callback)(struct presence_t *)  : function pointer of presence message callback function
00301  *   @param void(*error_msg_callback)(void *)                   : function pointer of error message callback function
00302  *   @return Yalgaar_Error_t                                    : it will return success or failure status of subscription.
00303  *   @brief                                                     : this function will use to subscribe specific topic with clientID. set callback_function for each message type.
00304  **********************************************************************************/
00305 Yalgaar_Error_t yalgaar::yalgaar_subscribe(char * subscribe_channel,void(* sub_mesg_callback)(char *),void(*presence_mesg_callback)(char *), void(*error_msg_callback)(char *))
00306 {
00307     char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
00308     if (subscribe_channel == NULL || subscribe_channel == "") {
00309         return SUBCRIPTION_NOT_VALID;
00310     }
00311     if(yalgaar_wrapper_validate_string(subscribe_channel) != SUCCESS) {
00312         return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
00313     } else {
00314         if(presence_mesg_callback != NULL)
00315             yalgaar_presence_message_recv=presence_mesg_callback;
00316         yalgaar_new_message=sub_mesg_callback;
00317         yalgaar_error_message=error_msg_callback;
00318         setCallback(subscribe_callback_handler);
00319         sprintf(sub_channel,"%s/%s",gclient_key,subscribe_channel);
00320         if(subscribe(sub_channel) == SUCCESS)
00321             return SUCCESS;
00322         else
00323             return FAILURE;
00324     }
00325 }
00326 
00327 /**********************************************************************************
00328  *   @name                                                      : Yalgaar_Error_t yalgaar::yalgaar_subscribes(uint8_t **subscribe_channel,void(* sub_mesg_callback)(void *),void(*presence_mesg_callback)(void *), void(*error_msg_callback)(void *))
00329  *   @param uint8_t * subscribe_channel                         : topic name of subscription
00330  *   @param void(* sub_mesg_callback)(void *)                   : function pointer of normal message receive callback function
00331  *   @param void(*presence_mesg_callback)(struct presence_t *)  : function pointer of presense message callback funcation
00332  *   @param void(*error_msg_callback)(void *)                   : function pointer of error message callback function
00333  *   @return Yalgaar_Error_t                                    : it will return success or failure status of subscription.
00334  *   @brief                                                     : this function will use to subscribe specific topic with clientID. set callback_function for each message type.
00335  **********************************************************************************/
00336 Yalgaar_Error_t yalgaar::yalgaar_subscribes(char **subscribe_channel,void(* sub_mesg_callback)(char *),void(*presence_mesg_callback)(char *), void(*error_msg_callback)(char *))
00337 {
00338     unsigned int iterator=0;
00339     Yalgaar_Error_t ret;
00340     bool sub_ret;
00341     char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
00342     if(presence_mesg_callback != NULL)
00343         yalgaar_presence_message_recv=presence_mesg_callback;
00344     yalgaar_new_message=sub_mesg_callback;
00345     yalgaar_error_message=error_msg_callback;
00346     setCallback(subscribe_callback_handler);
00347     for(iterator=0; subscribe_channel[iterator]!= '\0' ; iterator++) {
00348         if (subscribe_channel[iterator] == NULL || subscribe_channel[iterator] == "") {
00349             return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
00350         }
00351         if(yalgaar_wrapper_validate_string(subscribe_channel[iterator]) != SUCCESS) {
00352             ret = SUBCRIBE_CHANNEL_LENGTH_EXCEED;
00353             return ret;
00354         } else {
00355             memset(sub_channel,0,sizeof(sub_channel));
00356             sprintf(sub_channel,"%s/%s",gclient_key,subscribe_channel[iterator]);
00357             sub_ret = subscribe(sub_channel);
00358         }
00359     }
00360     if(sub_ret)
00361         return SUCCESS;
00362     else
00363         return FAILURE;
00364 }
00365 
00366 /**********************************************************************************
00367  *   @name                      : Yalgaar_Error_t yalgaar::yalgaar_unsubscribe(const char* topic)
00368  *   @param const char* topic   : channel name for unsubscribe specific topic/channel.
00369  *   @return Yalgaar_Error_t    : it will return success or failure status of unsubscribe method.
00370  *   @brief                     : this function is used to unsubscribe already subscribe topic.
00371  **********************************************************************************/
00372 Yalgaar_Error_t yalgaar::yalgaar_unsubscribe(const char* channel)
00373 {
00374 
00375     char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
00376     if(channel == NULL || channel == "") {
00377         return UNSUBSCRIBE_CHANNEL_LENGTH_EXCEED;
00378     }
00379     if(yalgaar_wrapper_validate_string(channel) != SUCCESS) {
00380         return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
00381     } else {
00382         sprintf(sub_channel,"%s/%s",gclient_key,channel);
00383         if(unsubscribe(sub_channel) == SUCCESS)
00384             return SUCCESS;
00385         else
00386             return FAILURE;
00387     }
00388 
00389 }
00390 /**********************************************************************************
00391  *   @name                      : int yalgaar::connection_state()
00392  *   @return int                : it will return retrun of connect reurn code
00393  *   @brief                     : this function is used to check state of connection state
00394  **********************************************************************************/
00395 void yalgaar::connection_state(bool ret)
00396 {
00397     int error_code;
00398     char err_message[YALGAAR_ERROR_MESSAGE_LENGTH]= {0};
00399     if (ret == SUCCESS) {
00400         connection_main_Callback("Connected successfully");
00401     } else {
00402         error_code = mqtt_state();
00403         enum_to_message(error_code,err_message);
00404         connection_main_Callback(err_message);
00405     }
00406 
00407 }
00408 /**********************************************************************************
00409  *   @name                      : boolean yalgaar::yalgaar_loop()
00410  *   @return boolean            : it will return success or failure status
00411  *   @brief                     : this function is used to continue to connection
00412  **********************************************************************************/
00413 void yalgaar::yalgaar_loop()
00414 {
00415     char err_message[YALGAAR_ERROR_MESSAGE_LENGTH]= {0};
00416     loop();
00417     if (pubsub_error_code >=108 && pubsub_error_code <= 111 ) {
00418         enum_to_message(pubsub_error_code,err_message);
00419         yalgaar_error_message(err_message);
00420         pubsub_error_code = 0;
00421     }
00422     if (pubsub_error_code >=121 && pubsub_error_code <= 123 ) {
00423         enum_to_message(pubsub_error_code,err_message);
00424         yalgaar_error_message(err_message);
00425         pubsub_error_code = 0;
00426     }
00427     if(pubsub_error_code >=115 && pubsub_error_code <= 120 ) {
00428         enum_to_message(pubsub_error_code,err_message);
00429         connection_main_Callback(err_message);
00430         pubsub_error_code = 0;
00431     }
00432 }
00433 /**********************************************************************************
00434  *   @name                      : boolean yalgaar::is_connected()
00435  *   @return boolean            : it will return success or failure status
00436  *   @brief                     : this function is used to cjheck yalgaar is connect or not
00437  **********************************************************************************/
00438 bool yalgaar::yalgaar_connected()
00439 {
00440     return connected();
00441 }
00442 /**********************************************************************************
00443  *   @name                      : void yalgaar::yalgaar_disconnect()
00444  *   @return Void               :
00445  *   @brief                     : this function is used to disconnect from yalgaar
00446  **********************************************************************************/
00447 void yalgaar::yalgaar_disconnect()
00448 {
00449     
00450     disconnect();
00451     connection_main_Callback("Successfully disconneted");
00452     return;
00453 }