Yalgaar mBed SDK for real-time messaging

Dependents:   YalgaarSDK

Fork of MQTT by Joerg Wende

yalgaar_api.cpp

Committer:
nileshvora
Date:
2017-03-14
Revision:
5:7dde43328c25
Parent:
4:013cbaaeda50

File content as of revision 5:7dde43328c25:

/** @fileName <yalgaar_api>
 *  @brief - <Yalgaar SDK APIS>
 *
 *  @Version:V:01:00:000
 *
 *
 * @Copyright:
 * Copyright (c) 2010 System Level Solution (India) pvt.ltd. Corporation.  All rights reserved.
 *
 * License: Free License for Yalgaar Users
 * Disclaimer:
 * SLS MAKES NO REPRESENTATION, WARRANTY, OR CONDITION OF ANY KIND, EXPRESS,
 * IMPLIED, STATUTORY, OR OTHERWISE OR IN ANY COMMUNICATION WITH YOU, INCLUDING,
 * BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY
 * QUALITY, FITNESS FOR ANY PARTICULAR PURPOSE, NONINFRINGEMENT, AND THEIR
 * EQUIVALENTS.
 */
#include "yalgaar_api.h"

Serial pc2(USBTX, USBRX, 115200);

void (* connection_main_Callback)(char *);
void (* yalgaar_presence_message_recv)(char *);
void (* yalgaar_error_message)(char *error);
void (* yalgaar_new_message)(char * message);
void parse_subscribe_message(char*,char*, unsigned int);
void subscribe_callback_handler(char*,char*, unsigned int);

char uuid_general[YALGAAR_MAX_UUID_STR_COUNT];
char gclient_key[YALGAAR_CLIENT_KEY_MAX_LENGTH];

const char *YALGAAR_ERROR_LIST[]= {
    "ClientId should not be null.",
    "Invalid ClientId.",
    "Invalid ClientKey.ClientKey is not registered. ",
    "Invalid Uuid.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
    "ClientKey is not active.",
    "SSL is not enable.",
    "The maximum connection limit has been reached.",
    "Invalid subscribe channel.",
    "Invalid subscribe channel.ClientKey does not match.",
    "Multiple subscribe channels are not allowed. Multiplexing is not enable.",
    "Invalid subscribe channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
    "Storage is not enable.",
    "Presence is not enable.",
    "Entered history channel has not been subscribed.",
    "Message can not be null.",
    "Invalid publish channel.",
    "Invalid publish channel.ClientKey does not match.",
    "Message count exceeds maximum limit.",
    "Message size exceeds maximum limit.",
    "Invalid publish channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50.",
    "Invalid UnSubscribe channel.",
    "Invalid UnSubscribe channel.ClientKey does not match.",
    "Invalid UnSubscribe channel.Only alpha numeric,hyphens,@,underscore allowed and maximum length must be 50."
};

/**********************************************************************************
 *   @name                      : yalgaar_error_t yalgaar_wrapper_validate_string(const char * str)
 *   @param const char * str    : char pointer str parameter contains string which have to validate.
 *   @return yalgaar_error_t                : function returns error id.
 *   @brief                     : validate the uuid for proper alpha numeric value(as per defined).
 **********************************************************************************/
Yalgaar_Error_t yalgaar_wrapper_validate_string(const char * str)
{
    char a = strlen(str);
    int i = 0;

    if(a > YALGAAR_MAX_CHANNEL_NAME_LENGTH) {
        return INVL_STRING;
    }
    for(i=0; i<a; i++) {
        if (0x3f < str[i]) {
            if(str[i] < 0x5b) {
                continue;
            }
        }
        if(0x30 <=str[i]) {
            if(str[i] <= 0x39) {
                continue;
            }
        }
        if(0x61 <=str[i]) {
            if(str[i] <= 0x7a) {
                continue;
            }
        }
        if(str[i] == 0x5f) {
            continue;
        }
        if(str[i] == 0x2d) {
            continue;
        }
        return INVL_STRING;
    }

    return SUCCESS;
}
/**********************************************************************************
 *   @name                  : static char *rand_string(char *str, size_t size)
 *   @param  char *str      : str is used to store generated random string for UUID.
 *   @param size_t size : size is used into string generation for random string length.
 *   @return void           :
 *   @brief                 : generate random string for dynamic UUID for topic string creation.
 **********************************************************************************/
void rand_string(char *str, size_t size)
{
    const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
    if (size) {
        size_t n;
        --size;
        for (n = 0; n < size; n++) {
            int key = rand() % (int) (sizeof charset - 1);
            str[n] = charset[key];
        }
        str[size] = '\0';
    }
}
/**********************************************************************************
*   @name                  : char* rand_string_alloc(size_t size)
*   @param size_t size     : size parameter is used to malloc size for random string.
*   @return char *         : returns generaed random string pointer.
*   @brief                 : memory allocate for variable to store rand string.
**********************************************************************************/
char* rand_string_alloc(size_t size)
{
    char *s = (char *)malloc(size + 1);
    if (s) {
        rand_string(s, size);
    }
    return s;
}

/**********************************************************************************
 *   @name                  : void enum_to_message(yalgaar_error_t *error_msg,unsigned char *errorString)
 *   @param  error_msg      : error_msg is int parameter for error message enum.
 *   @param  errorString    : errorString is char pointer, error string copy from YALGAAR_ERROR_LIST & stored into errorString
 *   @return void           :
 *   @brief                 : convert error Id(enum) to error message and set into char pointer.
 **********************************************************************************/
void yalgaar::enum_to_message(int error_msg,char *errorString)
{
    if(error_msg==CLIENT_NULL) {
        strncpy(errorString,YALGAAR_ERROR_LIST[0],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==CLIENT_NOT_VALID) {
        strncpy(errorString,YALGAAR_ERROR_LIST[1],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==CLIENT_KEY_NOT_REG) {
        strncpy(errorString,YALGAAR_ERROR_LIST[2],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==UUID_NOT_VALID) {
        strncpy(errorString,YALGAAR_ERROR_LIST[3],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==CLIENT_KEY_NOT_ACTIVE) {
        strncpy(errorString,YALGAAR_ERROR_LIST[4],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==SSL_NOT_ENABLE) {
        strncpy(errorString,YALGAAR_ERROR_LIST[5],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==CONNECTION_LIMIT_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[6],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==SUBCRIPTION_NOT_VALID) {
        strncpy(errorString,YALGAAR_ERROR_LIST[7],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==SUBCRIPTION_CLIENT_KEY_NOT_MATCH) {
        strncpy(errorString,YALGAAR_ERROR_LIST[8],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==MULTIPLE_SUBCRIBES_NOT_ALLOWED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[9],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==SUBCRIBE_CHANNEL_LENGTH_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[10],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==STORAGE_NOT_ENABLE) {
        strncpy(errorString,YALGAAR_ERROR_LIST[11],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==PRESENCE_NOT_ENABLE) {
        strncpy(errorString,YALGAAR_ERROR_LIST[12],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==HISTORY_CHANNEL_NOT_SUBCRIBE) {
        strncpy(errorString,YALGAAR_ERROR_LIST[13],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==MESSAGE_NOT_NULL) {
        strncpy(errorString,YALGAAR_ERROR_LIST[14],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==PUBLISH_CHANNEL_NOT_VALID) {
        strncpy(errorString,YALGAAR_ERROR_LIST[15],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==PUBLISH_CLIENT_KEY_NOT_MATCH) {
        strncpy(errorString,YALGAAR_ERROR_LIST[16],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==MESSAGE_CNT_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[17],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==MESSAGE_SIZE_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[18],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==MESSAGE_LENGTH_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[19],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==UNSUBSCRIBE_CHANNEL_NOT_VALID) {
        strncpy(errorString,YALGAAR_ERROR_LIST[20],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==UNSUBSCRIBE_CLIENT_KEY_NOT_MATCH) {
        strncpy(errorString,YALGAAR_ERROR_LIST[21],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else if(error_msg==UNSUBSCRIBE_CHANNEL_LENGTH_EXCEED) {
        strncpy(errorString,YALGAAR_ERROR_LIST[22],YALGAAR_ERROR_MESSAGE_LENGTH);
    } else {
        strcpy(errorString,"Undefined Error");
    }
    return;
}
/**********************************************************************************
 *   @name                      : void parse_subscribe_message(char* topic, char* payload, unsigned int length)
 *   @param char * topic        : topicName parameter have received message topic name.
 *   @param unsigned int length : payload_len parameter have Received message payload length.
 *   @param uint8_t* payload    : payload * have row data of received message for parsing
 *   @return void               : .
 *   @brief                     : filter message using subscribe message for specific message.
 **********************************************************************************/
void parse_subscribe_message(char* topic, char* payload, unsigned int length)
{
    char temppayload[length];
    char * start_string =NULL;
    memset(temppayload,0,length);
    for (int i=0; i<length; i++) {
        temppayload[i] = payload[i];
    }
    start_string = strstr(temppayload,"isPresence");
    if(start_string != NULL) {
        yalgaar_presence_message_recv(payload);
    } else {
        yalgaar_new_message(payload);
    }

}
/**********************************************************************************
 *   @name                                  : void subscribe_callback_handler(char* topic, char* payload, unsigned int length)
 *   @param char* topic                     : subscribe topic for yalgaar
 *   @param uint8_t* payload                : Payload of recieve message
 *   @param unsigned int length             : length of recieve mesaage
 *   @return void                           :
 *   @brief                                 : this function will called when any message received on specific subscribed topic.
 **********************************************************************************/
void subscribe_callback_handler(char* topic, char* payload, unsigned int length)
{
    parse_subscribe_message(topic,payload,length);
}

/**********************************************************************************
 *   @name                                          : Yalgaar_Error_t yalgaar::yalgaar_connect(const char* id,void(*connectionCallback)( int,char * ))
 *   @param char *clientKey                         : clientkey contains the yalgaar server clientKey for all SDK.
 *   @param void(*connectionCallback)( int,char* )  : connectionCallback is a function pointer of connect callback function.
 *   @return Yalgaar_Error_t                        : contains the success or failure status of connection.
 *   @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.
 **********************************************************************************/
Yalgaar_Error_t yalgaar::yalgaar_connect(const char* clientKey,const char *uuid,void(*connectionCallback)(char * ))
{
    char clientID[YALGAAR_CLIENT_DEFAULT_STRING_LEN];
    bool ret;

    //UUID Validation
    if(clientKey == NULL || clientKey == "") {
        return CLIENT_NULL;
    }
    if(uuid == NULL || uuid == "") {
        uuid = rand_string_alloc(YALGAAR_MAX_UUID_STR_COUNT);
        strncpy(uuid_general,uuid,sizeof(uuid_general));
    } else {
        if(yalgaar_wrapper_validate_string(uuid) != SUCCESS) {
            return UUID_NOT_VALID;
        }

        strncpy(uuid_general,uuid,sizeof(uuid_general));
    }
    sprintf(clientID,"%s/%s",clientKey,uuid_general);
    connection_main_Callback=connectionCallback;
    snprintf(gclient_key,sizeof(gclient_key),"%s",(char *)clientKey);
    ret=connect(clientID);
        wait(5.0f); 
    connection_state(ret);
    if (ret == 1)
        return SUCCESS;
    else
        return FAILURE;
}

/**********************************************************************************
 *   @name                      : Yalgaar_Error_t yalgaar_publish(const char *topic,char *payload)
 *   @param const char *topic   : channel name to publish on specific topic
 *   @param char *payload       : message string to publish
 *   @return Yalgaar_Error_t    : it will return success or failure status of publish message.
 *   @brief                     : this function is called to publish any message to specific topic.
 **********************************************************************************/
Yalgaar_Error_t yalgaar::yalgaar_publish(const char* topic, char* payload)
{
    char publish_channel[128]= {0};
    if(topic == NULL || topic == "") {
        return MESSAGE_LENGTH_EXCEED;
    }
    if(yalgaar_wrapper_validate_string(topic) != SUCCESS) {
        return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
    } else {
        if(payload=="" || payload==NULL) {
            return MESSAGE_NOT_NULL;
        }
    }
    sprintf(publish_channel,"%s/%s",gclient_key,topic);
    if(publish(publish_channel,payload) == SUCCESS) {
        return SUCCESS;
    } else {
        return FAILURE;
    }
}
/**********************************************************************************
 *   @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 *))
 *   @param char * subscribe_channel                            : topic name of subscription
 *   @param void(* sub_mesg_callback)(void *)                   : function pointer of normal message receive callback function
 *   @param void(*presence_mesg_callback)(struct presence_t *)  : function pointer of presence message callback function
 *   @param void(*error_msg_callback)(void *)                   : function pointer of error message callback function
 *   @return Yalgaar_Error_t                                    : it will return success or failure status of subscription.
 *   @brief                                                     : this function will use to subscribe specific topic with clientID. set callback_function for each message type.
 **********************************************************************************/
Yalgaar_Error_t yalgaar::yalgaar_subscribe(char * subscribe_channel,void(* sub_mesg_callback)(char *),void(*presence_mesg_callback)(char *), void(*error_msg_callback)(char *))
{
    char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
    if (subscribe_channel == NULL || subscribe_channel == "") {
        return SUBCRIPTION_NOT_VALID;
    }
    if(yalgaar_wrapper_validate_string(subscribe_channel) != SUCCESS) {
        return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
    } else {
        if(presence_mesg_callback != NULL)
            yalgaar_presence_message_recv=presence_mesg_callback;
        yalgaar_new_message=sub_mesg_callback;
        yalgaar_error_message=error_msg_callback;
        setCallback(subscribe_callback_handler);
        sprintf(sub_channel,"%s/%s",gclient_key,subscribe_channel);
        if(subscribe(sub_channel) == SUCCESS)
            return SUCCESS;
        else
            return FAILURE;
    }
}

/**********************************************************************************
 *   @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 *))
 *   @param uint8_t * subscribe_channel                         : topic name of subscription
 *   @param void(* sub_mesg_callback)(void *)                   : function pointer of normal message receive callback function
 *   @param void(*presence_mesg_callback)(struct presence_t *)  : function pointer of presense message callback funcation
 *   @param void(*error_msg_callback)(void *)                   : function pointer of error message callback function
 *   @return Yalgaar_Error_t                                    : it will return success or failure status of subscription.
 *   @brief                                                     : this function will use to subscribe specific topic with clientID. set callback_function for each message type.
 **********************************************************************************/
Yalgaar_Error_t yalgaar::yalgaar_subscribes(char **subscribe_channel,void(* sub_mesg_callback)(char *),void(*presence_mesg_callback)(char *), void(*error_msg_callback)(char *))
{
    unsigned int iterator=0;
    Yalgaar_Error_t ret;
    bool sub_ret;
    char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
    if(presence_mesg_callback != NULL)
        yalgaar_presence_message_recv=presence_mesg_callback;
    yalgaar_new_message=sub_mesg_callback;
    yalgaar_error_message=error_msg_callback;
    setCallback(subscribe_callback_handler);
    for(iterator=0; subscribe_channel[iterator]!= '\0' ; iterator++) {
        if (subscribe_channel[iterator] == NULL || subscribe_channel[iterator] == "") {
            return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
        }
        if(yalgaar_wrapper_validate_string(subscribe_channel[iterator]) != SUCCESS) {
            ret = SUBCRIBE_CHANNEL_LENGTH_EXCEED;
            return ret;
        } else {
            memset(sub_channel,0,sizeof(sub_channel));
            sprintf(sub_channel,"%s/%s",gclient_key,subscribe_channel[iterator]);
            sub_ret = subscribe(sub_channel);
        }
    }
    if(sub_ret)
        return SUCCESS;
    else
        return FAILURE;
}

/**********************************************************************************
 *   @name                      : Yalgaar_Error_t yalgaar::yalgaar_unsubscribe(const char* topic)
 *   @param const char* topic   : channel name for unsubscribe specific topic/channel.
 *   @return Yalgaar_Error_t    : it will return success or failure status of unsubscribe method.
 *   @brief                     : this function is used to unsubscribe already subscribe topic.
 **********************************************************************************/
Yalgaar_Error_t yalgaar::yalgaar_unsubscribe(const char* channel)
{

    char sub_channel[YALGAAR_MAX_CHANNEL_NAME_LENGTH];
    if(channel == NULL || channel == "") {
        return UNSUBSCRIBE_CHANNEL_LENGTH_EXCEED;
    }
    if(yalgaar_wrapper_validate_string(channel) != SUCCESS) {
        return SUBCRIBE_CHANNEL_LENGTH_EXCEED;
    } else {
        sprintf(sub_channel,"%s/%s",gclient_key,channel);
        if(unsubscribe(sub_channel) == SUCCESS)
            return SUCCESS;
        else
            return FAILURE;
    }

}
/**********************************************************************************
 *   @name                      : int yalgaar::connection_state()
 *   @return int                : it will return retrun of connect reurn code
 *   @brief                     : this function is used to check state of connection state
 **********************************************************************************/
void yalgaar::connection_state(bool ret)
{
    int error_code;
    char err_message[YALGAAR_ERROR_MESSAGE_LENGTH]= {0};
    if (ret == SUCCESS) {
        connection_main_Callback("Connected successfully");
    } else {
        error_code = mqtt_state();
        enum_to_message(error_code,err_message);
        connection_main_Callback(err_message);
    }

}
/**********************************************************************************
 *   @name                      : boolean yalgaar::yalgaar_loop()
 *   @return boolean            : it will return success or failure status
 *   @brief                     : this function is used to continue to connection
 **********************************************************************************/
void yalgaar::yalgaar_loop()
{
    char err_message[YALGAAR_ERROR_MESSAGE_LENGTH]= {0};
    loop();
    if (pubsub_error_code >=108 && pubsub_error_code <= 111 ) {
        enum_to_message(pubsub_error_code,err_message);
        yalgaar_error_message(err_message);
        pubsub_error_code = 0;
    }
    if (pubsub_error_code >=121 && pubsub_error_code <= 123 ) {
        enum_to_message(pubsub_error_code,err_message);
        yalgaar_error_message(err_message);
        pubsub_error_code = 0;
    }
    if(pubsub_error_code >=115 && pubsub_error_code <= 120 ) {
        enum_to_message(pubsub_error_code,err_message);
        connection_main_Callback(err_message);
        pubsub_error_code = 0;
    }
}
/**********************************************************************************
 *   @name                      : boolean yalgaar::is_connected()
 *   @return boolean            : it will return success or failure status
 *   @brief                     : this function is used to cjheck yalgaar is connect or not
 **********************************************************************************/
bool yalgaar::yalgaar_connected()
{
    return connected();
}
/**********************************************************************************
 *   @name                      : void yalgaar::yalgaar_disconnect()
 *   @return Void               :
 *   @brief                     : this function is used to disconnect from yalgaar
 **********************************************************************************/
void yalgaar::yalgaar_disconnect()
{
    
    disconnect();
    connection_main_Callback("Successfully disconneted");
    return;
}