Demo application for using the AT&T IoT Starter Kit Powered by AWS.

Dependencies:   SDFileSystem

Fork of ATT_AWS_IoT_demo by Anthony Phillips

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aws_iot_mqtt_embedded_client_wrapper.cpp Source File

aws_iot_mqtt_embedded_client_wrapper.cpp

00001 /*
00002  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License").
00005  * You may not use this file except in compliance with the License.
00006  * A copy of the License is located at
00007  *
00008  *  http://aws.amazon.com/apache2.0
00009  *
00010  * or in the "license" file accompanying this file. This file is distributed
00011  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
00012  * express or implied. See the License for the specific language governing
00013  * permissions and limitations under the License.
00014  */
00015 #include "timer_interface.h"
00016 #include "aws_iot_mqtt_interface.h"
00017 #include "MQTTClient.h"
00018 #include "aws_iot_config.h"
00019 #include "aws_iot_log.h"
00020 
00021 static Client c;
00022 
00023 static iot_disconnect_handler clientDisconnectHandler;
00024 
00025 static unsigned char writebuf[AWS_IOT_MQTT_TX_BUF_LEN];
00026 static unsigned char readbuf[AWS_IOT_MQTT_RX_BUF_LEN];
00027 
00028 const MQTTConnectParams MQTTConnectParamsDefault = {
00029         .enableAutoReconnect = 0,
00030         .pHostURL = AWS_IOT_MQTT_HOST,
00031         .port = AWS_IOT_MQTT_PORT,
00032         .pRootCALocation = NULL,
00033         .pDeviceCertLocation = NULL,
00034         .pDevicePrivateKeyLocation = NULL,
00035         .pClientID = NULL,
00036         .pUserName = NULL,
00037         .pPassword = NULL,
00038         .MQTTVersion = MQTT_3_1_1,
00039         .KeepAliveInterval_sec = 10,
00040         .isCleansession = true,
00041         .isWillMsgPresent = false,
00042         .will={.pTopicName = NULL, .pMessage = NULL, .isRetained = false, .qos = QOS_0},
00043         .mqttCommandTimeout_ms = 1000,
00044         .tlsHandshakeTimeout_ms = 2000,
00045         .isSSLHostnameVerify = true,
00046         .disconnectHandler = NULL
00047 };
00048 
00049 const MQTTPublishParams MQTTPublishParamsDefault={
00050         .pTopic = NULL,
00051         .MessageParams = {.qos = QOS_0, .isRetained=false, .isDuplicate = false, .id = 0, .pPayload = NULL, .PayloadLen = 0}
00052 };
00053 const MQTTSubscribeParams MQTTSubscribeParamsDefault={
00054         .pTopic = NULL,
00055         .qos = QOS_0,
00056         .mHandler = NULL
00057 };
00058 const MQTTCallbackParams MQTTCallbackParamsDefault={
00059         .pTopicName = NULL,
00060         .TopicNameLen = 0,
00061         .MessageParams = {.qos = QOS_0, .isRetained=false, .isDuplicate = false, .id = 0, .pPayload = NULL, .PayloadLen = 0}
00062 };
00063 const MQTTMessageParams MQTTMessageParamsDefault={
00064         .qos = QOS_0,
00065         .isRetained=false,
00066         .isDuplicate = false,
00067         .id = 0,
00068         .pPayload = NULL,
00069         .PayloadLen = 0
00070 };
00071 const MQTTwillOptions MQTTwillOptionsDefault={
00072         .pTopicName = NULL,
00073         .pMessage = NULL,
00074         .isRetained = false,
00075         .qos = QOS_0
00076 };
00077 
00078 #define GETLOWER4BYTES 0x0FFFFFFFF
00079 void pahoMessageCallback(MessageData* md) {
00080     MQTTMessage* message = md->message;
00081     MQTTCallbackParams params;
00082 
00083     // early exit if we do not have a valid callback pointer
00084     if (md->applicationHandler == NULL) {
00085         return;
00086     }
00087 
00088     if (NULL != md->topicName->lenstring.data) {
00089         params.pTopicName = md->topicName->lenstring.data;
00090         params.TopicNameLen = (uint16_t)(md->topicName->lenstring.len);
00091     }
00092     if (NULL != message) {
00093         params.MessageParams.PayloadLen = message->payloadlen & GETLOWER4BYTES;
00094         params.MessageParams.pPayload = (char*) message->payload;
00095         params.MessageParams.isDuplicate = message->dup;
00096         params.MessageParams.qos = (QoSLevel)message->qos;
00097         params.MessageParams.isRetained = message->retained;
00098         params.MessageParams.id = message->id;
00099     }
00100 
00101     ((iot_message_handler)(md->applicationHandler))(params);
00102 }
00103 
00104 void pahoDisconnectHandler(void) {
00105     if(NULL != clientDisconnectHandler) {
00106         clientDisconnectHandler();
00107     }
00108 }
00109 
00110 static bool isPowerCycle = true;
00111 
00112 IoT_Error_t aws_iot_mqtt_connect(MQTTConnectParams *pParams) {
00113     IoT_Error_t rc = NONE_ERROR;
00114     MQTTReturnCode pahoRc = SUCCESS;
00115     
00116     if(NULL == pParams || NULL == pParams->pClientID || NULL == pParams->pHostURL) {
00117         return NULL_VALUE_ERROR;
00118     }
00119 
00120     TLSConnectParams TLSParams;
00121     TLSParams.DestinationPort = pParams->port;
00122     TLSParams.pDestinationURL = pParams->pHostURL;
00123     TLSParams.pDeviceCertLocation = pParams->pDeviceCertLocation;
00124     TLSParams.pDevicePrivateKeyLocation = pParams->pDevicePrivateKeyLocation;
00125     TLSParams.pRootCALocation = pParams->pRootCALocation;
00126     TLSParams.timeout_ms = pParams->tlsHandshakeTimeout_ms;
00127     TLSParams.ServerVerificationFlag = pParams->isSSLHostnameVerify;
00128 
00129     DEBUG("...subscribe");
00130     // This implementation assumes you are not going to switch between cleansession 1 to 0
00131     // As we don't have a default subscription handler support in the MQTT client every time a device power cycles it has to re-subscribe to let the MQTT client to pass the message up to the application callback.
00132     // The default message handler will be implemented in the future revisions.
00133     if(pParams->isCleansession || isPowerCycle){
00134         pahoRc = MQTTClient(&c, (unsigned int)(pParams->mqttCommandTimeout_ms), writebuf,
00135                    AWS_IOT_MQTT_TX_BUF_LEN, readbuf, AWS_IOT_MQTT_RX_BUF_LEN,
00136                    pParams->enableAutoReconnect, iot_tls_init, &TLSParams);
00137         if(SUCCESS != pahoRc) {
00138             return CONNECTION_ERROR;
00139         }
00140         isPowerCycle = false;
00141     }
00142 
00143     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00144 
00145     DEBUG("...MQTTVersion");
00146     data.willFlag = pParams->isWillMsgPresent;
00147     // compatible type for MQTT_Ver_t
00148     switch (pParams->MQTTVersion) {
00149     case MQTT_3_1:
00150         data.MQTTVersion = (unsigned char) (3);
00151         break;
00152     case MQTT_3_1_1:
00153         data.MQTTVersion = (unsigned char) (4);
00154         break;
00155     default:
00156         data.MQTTVersion = (unsigned char) (4); // default MQTT version = 3.1.1
00157     }
00158 
00159     // register our disconnect handler, save customer's handler
00160     setDisconnectHandler(&c, pahoDisconnectHandler);
00161     clientDisconnectHandler = pParams->disconnectHandler;
00162 
00163     data.clientID.cstring = pParams->pClientID;
00164     data.username.cstring = pParams->pUserName;
00165     data.password.cstring = pParams->pPassword;
00166     data.will.topicName.cstring = (char*)pParams->will.pTopicName;
00167     data.will.message.cstring = (char*)pParams->will.pMessage;
00168     data.will.qos = (enum QoS)pParams->will.qos;
00169     data.will.retained = pParams->will.isRetained;
00170     data.keepAliveInterval = pParams->KeepAliveInterval_sec;
00171     data.cleansession = pParams->isCleansession;
00172 
00173     DEBUG("...MQTTConnect");
00174     pahoRc = MQTTConnect(&c, &data);
00175     if(MQTT_NETWORK_ALREADY_CONNECTED_ERROR == pahoRc) {
00176         rc = NETWORK_ALREADY_CONNECTED;
00177     } else if(SUCCESS != pahoRc) {
00178         rc = CONNECTION_ERROR;
00179     }
00180 
00181     return rc;
00182 }
00183 
00184 IoT_Error_t aws_iot_mqtt_subscribe(MQTTSubscribeParams *pParams) {
00185     IoT_Error_t rc = NONE_ERROR;
00186 
00187     if (0 != MQTTSubscribe(&c, pParams->pTopic, (enum QoS)pParams->qos, pahoMessageCallback, (void (*)(void))(pParams->mHandler))) {
00188             rc = SUBSCRIBE_ERROR;
00189     }
00190     return rc;
00191 }
00192 
00193 IoT_Error_t aws_iot_mqtt_publish(MQTTPublishParams *pParams) {
00194     IoT_Error_t rc = NONE_ERROR;
00195 
00196     MQTTMessage Message;
00197     Message.dup = pParams->MessageParams.isDuplicate;
00198     Message.id = pParams->MessageParams.id;
00199     Message.payload = pParams->MessageParams.pPayload;
00200     Message.payloadlen = pParams->MessageParams.PayloadLen;
00201     Message.qos = (enum QoS)pParams->MessageParams.qos;
00202     Message.retained = pParams->MessageParams.isRetained;
00203 
00204     if(0 != MQTTPublish(&c, pParams->pTopic, &Message)){
00205         rc = PUBLISH_ERROR;
00206     }
00207 
00208     return rc;
00209 }
00210 
00211 IoT_Error_t aws_iot_mqtt_unsubscribe(char *pTopic) {
00212     IoT_Error_t rc = NONE_ERROR;
00213 
00214     if(0 != MQTTUnsubscribe(&c, pTopic)){
00215         rc = UNSUBSCRIBE_ERROR;
00216     }
00217     return rc;
00218 }
00219 
00220 IoT_Error_t aws_iot_mqtt_disconnect() {
00221     IoT_Error_t rc = NONE_ERROR;
00222 
00223     if(0 != MQTTDisconnect(&c)){
00224         rc = DISCONNECT_ERROR;
00225     }
00226 
00227     return rc;
00228 }
00229 
00230 IoT_Error_t aws_iot_mqtt_yield(int timeout) {
00231     MQTTReturnCode pahoRc = MQTTYield(&c, timeout);
00232     IoT_Error_t rc = NONE_ERROR;
00233     if(MQTT_NETWORK_RECONNECTED == pahoRc){
00234         INFO("aws_iot_mqtt_yield() RECONNECT_SUCCESSFUL");
00235         rc = RECONNECT_SUCCESSFUL;
00236     } else if(SUCCESS == pahoRc){
00237         //INFO("aws_iot_mqtt_yield() NONE_ERROR");
00238         rc = NONE_ERROR;
00239     } else if(MQTT_NULL_VALUE_ERROR == pahoRc) {
00240         INFO("aws_iot_mqtt_yield() NULL_VALUE_ERROR");
00241         rc = NULL_VALUE_ERROR;
00242     } else if(MQTT_NETWORK_DISCONNECTED_ERROR == pahoRc) {
00243         INFO("aws_iot_mqtt_yield() NETWORK_DISCONNECTED");
00244         rc = NETWORK_DISCONNECTED;
00245     } else if(MQTT_RECONNECT_TIMED_OUT == pahoRc) {
00246         INFO("aws_iot_mqtt_yield() NETWORK_RECONNECT_TIMED_OUT");
00247         rc = NETWORK_RECONNECT_TIMED_OUT;
00248     } else if(MQTT_ATTEMPTING_RECONNECT == pahoRc) {
00249         INFO("aws_iot_mqtt_yield() NETWORK_ATTEMPTING_RECONNECT");
00250         rc = NETWORK_ATTEMPTING_RECONNECT;
00251     } else if(MQTT_BUFFER_RX_MESSAGE_INVALID == pahoRc){
00252         INFO("aws_iot_mqtt_yield() RX_MESSAGE_INVALID");
00253         rc = RX_MESSAGE_INVALID;
00254     } else if(MQTTPACKET_BUFFER_TOO_SHORT == pahoRc){
00255         INFO("aws_iot_mqtt_yield() RX_MESSAGE_BIGGER_THAN_MQTT_RX_BUF");
00256         rc = RX_MESSAGE_BIGGER_THAN_MQTT_RX_BUF;
00257     } else {
00258         INFO("aws_iot_mqtt_yield() YIELD_ERROR");
00259         rc = YIELD_ERROR;
00260     }
00261 
00262     return rc;
00263 }
00264 
00265 IoT_Error_t aws_iot_mqtt_attempt_reconnect() {
00266     MQTTReturnCode pahoRc = MQTTAttemptReconnect(&c);
00267     IoT_Error_t rc = RECONNECT_SUCCESSFUL;
00268     if(MQTT_NETWORK_RECONNECTED == pahoRc){
00269         rc = RECONNECT_SUCCESSFUL;
00270     } else if(MQTT_NULL_VALUE_ERROR == pahoRc) {
00271         rc = NULL_VALUE_ERROR;
00272     } else if(MQTT_NETWORK_DISCONNECTED_ERROR == pahoRc) {
00273         rc = NETWORK_DISCONNECTED;
00274     } else if(MQTT_RECONNECT_TIMED_OUT == pahoRc) {
00275         rc = NETWORK_RECONNECT_TIMED_OUT;
00276     } else if(MQTT_NETWORK_ALREADY_CONNECTED_ERROR == pahoRc) {
00277         rc = NETWORK_ALREADY_CONNECTED;
00278     } else {
00279         rc = GENERIC_ERROR;
00280     }
00281 
00282     return rc;
00283 }
00284 
00285 IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(bool value) {
00286     MQTTReturnCode rc = setAutoReconnectEnabled(&c, (uint8_t) value);
00287 
00288     if(MQTT_NULL_VALUE_ERROR == rc) {
00289         return NULL_VALUE_ERROR;
00290     }
00291 
00292     return NONE_ERROR;
00293 }
00294 
00295 bool aws_iot_is_mqtt_connected(void) {
00296     return MQTTIsConnected(&c);
00297 }
00298 
00299 bool aws_iot_is_autoreconnect_enabled(void) {
00300     return MQTTIsAutoReconnectEnabled(&c);
00301 }
00302 
00303 void aws_iot_mqtt_init(MQTTClient_t *pClient){
00304     pClient->connect = aws_iot_mqtt_connect;
00305     pClient->disconnect = aws_iot_mqtt_disconnect;
00306     pClient->isConnected = aws_iot_is_mqtt_connected;
00307     pClient->reconnect = aws_iot_mqtt_attempt_reconnect;
00308     pClient->publish = aws_iot_mqtt_publish;
00309     pClient->subscribe = aws_iot_mqtt_subscribe;
00310     pClient->unsubscribe = aws_iot_mqtt_unsubscribe;
00311     pClient->yield = aws_iot_mqtt_yield;
00312     pClient->isAutoReconnectEnabled = aws_iot_is_autoreconnect_enabled;
00313     pClient->setAutoReconnectStatus = aws_iot_mqtt_autoreconnect_set_status;
00314 }
00315 
00316