void parseInputArgsForConnectParams(int argc, char** argv) { int opt; while (-1 != (opt = getopt(argc, argv, "h:p:c:"))) { switch (opt) { case 'h': strcpy(HostAddress, optarg); IOT_DEBUG("Host %s", optarg); break; case 'p': port = atoi(optarg); IOT_DEBUG("arg %s", optarg); break; case 'c': strcpy(certDirectory, optarg); IOT_DEBUG("cert root directory %s", optarg); break; case '?': if (optopt == 'c') { IOT_ERROR("Option -%c requires an argument.", optopt); } else if (isprint(optopt)) { IOT_WARN("Unknown option `-%c'.", optopt); } else { IOT_WARN("Unknown option character `\\x%x'.", optopt); } break; default: IOT_ERROR("ERROR in command line argument parsing"); break; } } }
static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { int32_t tokenCount; uint8_t i; void *pJsonHandler = NULL; char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; IOT_UNUSED(pClient); IOT_UNUSED(topicNameLen); IOT_UNUSED(pData); if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) { IOT_WARN("Payload larger than RX Buffer"); return; } memcpy(shadowRxBuf, params->payload, params->payloadLen); shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { IOT_WARN("Received JSON is not valid"); return; } if(isAckForMyThingName(topicName)) { uint32_t tempVersionNumber = 0; if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { if(tempVersionNumber > shadowJsonVersionNum) { shadowJsonVersionNum = tempVersionNumber; } } } if(extractClientToken(shadowRxBuf, temporaryClientToken)) { for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { if(!AckWaitList[i].isFree) { if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { Shadow_Ack_Status_t status; if(strstr(topicName, "accepted") != NULL) { status = SHADOW_ACK_ACCEPTED; } else if(strstr(topicName, "rejected") != NULL) { status = SHADOW_ACK_REJECTED; } else { continue; } /* status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED */ if(AckWaitList[i].callback != NULL) { AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, shadowRxBuf, AckWaitList[i].pCallbackContext); } unsubscribeFromAcceptedAndRejected(i); AckWaitList[i].isFree = true; return; } } } } }
static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { int32_t tokenCount; uint32_t i = 0; void *pJsonHandler = NULL; int32_t DataPosition; uint32_t dataLength; uint32_t tempVersionNumber = 0; FUNC_ENTRY; IOT_UNUSED(pClient); IOT_UNUSED(topicName); IOT_UNUSED(topicNameLen); IOT_UNUSED(pData); if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) { IOT_WARN("Payload larger than RX Buffer"); return; } memcpy(shadowRxBuf, params->payload, params->payloadLen); shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { IOT_WARN("Received JSON is not valid"); return; } if(shadowDiscardOldDeltaFlag) { if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { if(tempVersionNumber > shadowJsonVersionNum) { shadowJsonVersionNum = tempVersionNumber; } else { IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber, shadowJsonVersionNum); return; } } } for(i = 0; i < tokenTableIndex; i++) { if(!tokenTable[i].isFree) { if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount, (jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) { if(tokenTable[i].callback != NULL) { tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength, (jsonStruct_t *) tokenTable[i].pStruct); } } } } }
IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not an integer"); return JSON_PARSE_ERROR; } if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu16, i))) { IOT_WARN("Token was not an unsigned integer."); return JSON_PARSE_ERROR; } return SUCCESS; }
IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not a double."); return JSON_PARSE_ERROR; } if(1 != sscanf(jsonString + token->start, "%lf", d)) { IOT_WARN("Token was not a double."); return JSON_PARSE_ERROR; } return SUCCESS; }
IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not a float."); return JSON_PARSE_ERROR; } if(1 != sscanf(jsonString + token->start, "%f", f)) { IOT_WARN("Token was not a float."); return JSON_PARSE_ERROR; } return SUCCESS; }
IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not an integer"); return JSON_PARSE_ERROR; } if(1 != sscanf(jsonString + token->start, "%" SCNi32, i)) { IOT_WARN("Token was not an integer."); return JSON_PARSE_ERROR; } return SUCCESS; }
bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken) { int32_t tokenCount, i; uint8_t length; jsmntok_t ClientJsonToken; jsmn_init(&shadowJsonParser); tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); if(tokenCount < 0) { IOT_WARN("Failed to parse JSON: %d\n", tokenCount); return false; } /* Assume the top-level element is an object */ if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { return false; } for(i = 1; i < tokenCount; i++) { if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) { ClientJsonToken = jsonTokenStruct[i + 1]; length = (uint8_t) (ClientJsonToken.end - ClientJsonToken.start); strncpy(pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length); pExtractedClientToken[length] = '\0'; return true; } } return false; }
void parseInputArgsForConnectParams(int argc, char **argv) { int opt; while (-1 != (opt = getopt(argc, argv, "h:p:c:t:s:"))) { switch (opt) { case 'h': strcpy(HostAddress, optarg); IOT_DEBUG("host %s\n", optarg); break; case 'p': port = atoi(optarg); IOT_DEBUG("port %s\n", optarg); break; case 'c': strcpy(certDirectory, optarg); IOT_DEBUG("cert root directory %s\n", optarg); break; case 't': strcpy(publishTopicName, optarg); IOT_DEBUG("publish topic name: %s\n", optarg); break; case 'f': strcpy(filename, optarg); IOT_DEBUG("config file %s", optarg); break; case 's': strcpy(subscribeTopicName, optarg); IOT_DEBUG("subscribe topic name: %s\n", optarg); break; case '?': if (optopt == 'c') { IOT_ERROR("Option -%c requires an argument.", optopt); } else if (isprint(optopt)) { IOT_WARN("Unknown option `-%c'.", optopt); } else { IOT_WARN("Unknown option character `\\x%x'.", optopt); } break; default: IOT_ERROR("Error in command line argument parsing"); break; } } }
bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) { FUNC_ENTRY; if(NULL == pClient) { IOT_WARN(" Client is null! "); FUNC_EXIT_RC(false); } FUNC_EXIT_RC(pClient->clientStatus.isAutoReconnectEnabled); }
IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not a primitive."); return JSON_PARSE_ERROR; } if(jsonString[token->start] == 't' && jsonString[token->start + 1] == 'r' && jsonString[token->start + 2] == 'u' && jsonString[token->start + 3] == 'e') { *b = true; } else if(jsonString[token->start] == 'f' && jsonString[token->start + 1] == 'a' && jsonString[token->start + 2] == 'l' && jsonString[token->start + 3] == 's' && jsonString[token->start + 4] == 'e') { *b = false; } else { IOT_WARN("Token was not a bool."); return JSON_PARSE_ERROR; } return SUCCESS; }
IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not an integer"); return JSON_PARSE_ERROR; } uint32_t i_word; if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%" SCNu32, &i_word))) { IOT_WARN("Token was not an unsigned integer."); return JSON_PARSE_ERROR; } if (i_word > UINT8_MAX) { IOT_WARN("Token value %u exceeds 8 bits", i_word); return JSON_PARSE_ERROR; } *i = i_word; return SUCCESS; }
IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) { if(token->type != JSMN_PRIMITIVE) { IOT_WARN("Token was not an integer"); return JSON_PARSE_ERROR; } int32_t i_word; if(1 != sscanf(jsonString + token->start, "%" SCNi32, &i_word)) { IOT_WARN("Token was not an integer."); return JSON_PARSE_ERROR; } if(i_word < INT8_MIN || i_word > INT8_MAX) { IOT_WARN("Token value %d out of range for 8-bit int", i_word); return JSON_PARSE_ERROR; } *i = i_word; return SUCCESS; }
IoT_Error_t parseStringValue(char *buf, const char *jsonString, jsmntok_t *token) { uint16_t size = 0; if(token->type != JSMN_STRING) { IOT_WARN("Token was not a string."); return JSON_PARSE_ERROR; } size = (uint16_t) (token->end - token->start); memcpy(buf, jsonString + token->start, size); buf[size] = '\0'; return SUCCESS; }
void disconnectCallbackHandler(AWS_IoT_Client *pClient, void *data) { IOT_WARN("MQTT Disconnect"); IoT_Error_t rc = FAILURE; if (NULL == pClient) { return; } IOT_UNUSED(data); if (aws_iot_is_autoreconnect_enabled(pClient)) { IOT_INFO("Auto Reconnect is enabled, Reconnecting attempt will start now"); } else { IOT_WARN("Auto Reconnect not enabled. Starting manual reconnect..."); rc = aws_iot_mqtt_attempt_reconnect(pClient); if (NETWORK_RECONNECTED == rc) { IOT_WARN("Manual Reconnect Successful"); } else { IOT_WARN("Manual Reconnect Failed - %d", rc); } } }
bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount) { int32_t tokenCount; jsmn_init(&shadowJsonParser); tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); if(tokenCount < 0) { IOT_WARN("Failed to parse JSON: %d\n", tokenCount); return false; } /* Assume the top-level element is an object */ if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { IOT_WARN("Top Level is not an object\n"); return false; } pJsonHandler = (void *) jsonTokenStruct; *pTokenCount = tokenCount; return true; }
bool isReceivedJsonValid(const char *pJsonDocument) { int32_t tokenCount; jsmn_init(&shadowJsonParser); tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); if(tokenCount < 0) { IOT_WARN("Failed to parse JSON: %d\n", tokenCount); return false; } /* Assume the top-level element is an object */ if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { return false; } return true; }
bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) { bool isConnected; FUNC_ENTRY; if(NULL == pClient) { IOT_WARN(" Client is null! "); FUNC_EXIT_RC(false); } switch(pClient->clientStatus.clientState) { case CLIENT_STATE_INVALID: case CLIENT_STATE_INITIALIZED: case CLIENT_STATE_CONNECTING: isConnected = false; break; case CLIENT_STATE_CONNECTED_IDLE: case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: isConnected = true; break; case CLIENT_STATE_DISCONNECTING: case CLIENT_STATE_DISCONNECTED_ERROR: case CLIENT_STATE_DISCONNECTED_MANUALLY: case CLIENT_STATE_PENDING_RECONNECT: default: isConnected = false; break; } FUNC_EXIT_RC(isConnected); }
int main(int argc, char **argv) { bool infinitePublishFlag = true; char rootCA[PATH_MAX + 1]; char clientCRT[PATH_MAX + 1]; char clientKey[PATH_MAX + 1]; char CurrentWD[PATH_MAX + 1]; char cPayload[100]; int32_t i = 0; IoT_Error_t rc = FAILURE; AWS_IoT_Client client; IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; IoT_Publish_Message_Params paramsQOS0; IoT_Publish_Message_Params paramsQOS1; parseInputArgsForConnectParams(argc, argv); IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); getcwd(CurrentWD, sizeof(CurrentWD)); snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); IOT_DEBUG("rootCA %s", rootCA); IOT_DEBUG("clientCRT %s", clientCRT); IOT_DEBUG("clientKey %s", clientKey); mqttInitParams.enableAutoReconnect = false; // We enable this later below mqttInitParams.pHostURL = HostAddress; mqttInitParams.port = port; mqttInitParams.pRootCALocation = rootCA; mqttInitParams.pDeviceCertLocation = clientCRT; mqttInitParams.pDevicePrivateKeyLocation = clientKey; mqttInitParams.mqttCommandTimeout_ms = 20000; mqttInitParams.tlsHandshakeTimeout_ms = 5000; mqttInitParams.isSSLHostnameVerify = true; mqttInitParams.disconnectHandler = disconnectCallbackHandler; mqttInitParams.disconnectHandlerData = NULL; rc = aws_iot_mqtt_init(&client, &mqttInitParams); if(SUCCESS != rc) { IOT_ERROR("aws_iot_mqtt_init returned error : %d ", rc); return rc; } connectParams.keepAliveIntervalInSec = 10; connectParams.isCleanSession = true; connectParams.MQTTVersion = MQTT_3_1_1; connectParams.pClientID = AWS_IOT_MQTT_CLIENT_ID; connectParams.clientIDLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); connectParams.isWillMsgPresent = false; IOT_INFO("Connecting..."); rc = aws_iot_mqtt_connect(&client, &connectParams); if(SUCCESS != rc) { IOT_ERROR("Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); return rc; } /* * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL */ rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); if(SUCCESS != rc) { IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); return rc; } IOT_INFO("Subscribing..."); rc = aws_iot_mqtt_subscribe(&client, "sdkTest/sub", 11, QOS0, iot_subscribe_callback_handler, NULL); if(SUCCESS != rc) { IOT_ERROR("Error subscribing : %d ", rc); return rc; } sprintf(cPayload, "%s : %d ", "hello from SDK", i); paramsQOS0.qos = QOS0; paramsQOS0.payload = (void *) cPayload; paramsQOS0.isRetained = 0; paramsQOS1.qos = QOS1; paramsQOS1.payload = (void *) cPayload; paramsQOS1.isRetained = 0; if(publishCount != 0) { infinitePublishFlag = false; } while((NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) && (publishCount > 0 || infinitePublishFlag)) { //Max time the yield function will wait for read messages rc = aws_iot_mqtt_yield(&client, 100); if(NETWORK_ATTEMPTING_RECONNECT == rc) { // If the client is attempting to reconnect we will skip the rest of the loop. continue; } IOT_INFO("-->sleep"); sleep(1); sprintf(cPayload, "%s : %d ", "hello from SDK QOS0", i++); paramsQOS0.payloadLen = strlen(cPayload); rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS0); if(publishCount > 0) { publishCount--; } sprintf(cPayload, "%s : %d ", "hello from SDK QOS1", i++); paramsQOS1.payloadLen = strlen(cPayload); rc = aws_iot_mqtt_publish(&client, "sdkTest/sub", 11, ¶msQOS1); if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { IOT_WARN("QOS1 publish ack not received.\n"); rc = SUCCESS; } if(publishCount > 0) { publishCount--; } } if(SUCCESS != rc) { IOT_ERROR("An error occurred in the loop.\n"); } else { IOT_INFO("Publish done\n"); } return rc; }