/* * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ /** * @file aws_iot_shadow.c * @brief Shadow client API definitions */ #ifdef __cplusplus extern "C" { #endif #include #include "aws_iot_mqtt_client_interface.h" #include "aws_iot_shadow_interface.h" #include "aws_iot_error.h" #include "aws_iot_log.h" #include "aws_iot_shadow_actions.h" #include "aws_iot_shadow_json.h" #include "aws_iot_shadow_key.h" #include "aws_iot_shadow_records.h" const ShadowInitParameters_t ShadowInitParametersDefault = {(char *) AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, NULL, NULL, NULL, false, NULL}; const ShadowConnectParameters_t ShadowConnectParametersDefault = {(char *) AWS_IOT_MY_THING_NAME, (char *) AWS_IOT_MQTT_CLIENT_ID, 0, NULL}; static char deleteAcceptedTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES]; void aws_iot_shadow_reset_last_received_version(void) { shadowJsonVersionNum = 0; } uint32_t aws_iot_shadow_get_last_received_version(void) { return shadowJsonVersionNum; } void aws_iot_shadow_enable_discard_old_delta_msgs(void) { shadowDiscardOldDeltaFlag = true; } void aws_iot_shadow_disable_discard_old_delta_msgs(void) { shadowDiscardOldDeltaFlag = false; } IoT_Error_t aws_iot_shadow_free(AWS_IoT_Client *pClient) { IoT_Error_t rc; if (NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } rc = aws_iot_mqtt_free(pClient); FUNC_EXIT_RC(rc); } IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t *pParams) { IoT_Client_Init_Params mqttInitParams = IoT_Client_Init_Params_initializer; IoT_Error_t rc; FUNC_ENTRY; if(NULL == pClient || NULL == pParams) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } mqttInitParams.enableAutoReconnect = pParams->enableAutoReconnect; mqttInitParams.pHostURL = pParams->pHost; mqttInitParams.port = pParams->port; mqttInitParams.pRootCALocation = pParams->pRootCA; mqttInitParams.pDeviceCertLocation = pParams->pClientCRT; mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey; mqttInitParams.mqttPacketTimeout_ms = 5000; mqttInitParams.mqttCommandTimeout_ms = 20000; mqttInitParams.tlsHandshakeTimeout_ms = 5000; mqttInitParams.isSSLHostnameVerify = true; mqttInitParams.disconnectHandler = pParams->disconnectHandler; rc = aws_iot_mqtt_init(pClient, &mqttInitParams); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } resetClientTokenSequenceNum(); aws_iot_shadow_reset_last_received_version(); initDeltaTokens(); FUNC_EXIT_RC(SUCCESS); } IoT_Error_t aws_iot_shadow_connect(AWS_IoT_Client *pClient, ShadowConnectParameters_t *pParams) { IoT_Error_t rc = SUCCESS; uint16_t deleteAcceptedTopicLen; IoT_Client_Connect_Params ConnectParams = iotClientConnectParamsDefault; FUNC_ENTRY; if(NULL == pClient || NULL == pParams || NULL == pParams->pMqttClientId) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } snprintf(myThingName, MAX_SIZE_OF_THING_NAME, "%s", pParams->pMyThingName); snprintf(mqttClientID, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES, "%s", pParams->pMqttClientId); ConnectParams.keepAliveIntervalInSec = 600; // NOTE: Temporary fix ConnectParams.MQTTVersion = MQTT_3_1_1; ConnectParams.isCleanSession = true; ConnectParams.isWillMsgPresent = false; ConnectParams.pClientID = pParams->pMqttClientId; ConnectParams.clientIDLen = pParams->mqttClientIdLen; ConnectParams.pPassword = NULL; ConnectParams.pUsername = NULL; rc = aws_iot_mqtt_connect(pClient, &ConnectParams); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } initializeRecords(pClient); if(NULL != pParams->deleteActionHandler) { snprintf(deleteAcceptedTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/delete/accepted", myThingName); deleteAcceptedTopicLen = (uint16_t) strlen(deleteAcceptedTopic); rc = aws_iot_mqtt_subscribe(pClient, deleteAcceptedTopic, deleteAcceptedTopicLen, QOS1, pParams->deleteActionHandler, (void *) myThingName); } FUNC_EXIT_RC(rc); } IoT_Error_t aws_iot_shadow_register_delta(AWS_IoT_Client *pMqttClient, jsonStruct_t *pStruct) { if(NULL == pMqttClient || NULL == pStruct) { return NULL_VALUE_ERROR; } if(!aws_iot_mqtt_is_client_connected(pMqttClient)) { return MQTT_CONNECTION_ERROR; } return registerJsonTokenOnDelta(pStruct); } IoT_Error_t aws_iot_shadow_yield(AWS_IoT_Client *pClient, uint32_t timeout) { if(NULL == pClient) { return NULL_VALUE_ERROR; } HandleExpiredResponseCallbacks(); return aws_iot_mqtt_yield(pClient, timeout); } IoT_Error_t aws_iot_shadow_disconnect(AWS_IoT_Client *pClient) { return aws_iot_mqtt_disconnect(pClient); } IoT_Error_t aws_iot_shadow_update(AWS_IoT_Client *pClient, const char *pThingName, char *pJsonString, fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { IoT_Error_t rc; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } if(!aws_iot_mqtt_is_client_connected(pClient)) { FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); } rc = aws_iot_shadow_internal_action(pThingName, SHADOW_UPDATE, pJsonString, strlen(pJsonString), callback, pContextData, timeout_seconds, isPersistentSubscribe); FUNC_EXIT_RC(rc); } IoT_Error_t aws_iot_shadow_delete(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { char deleteRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; IoT_Error_t rc; FUNC_ENTRY; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } if(!aws_iot_mqtt_is_client_connected(pClient)) { FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); } rc = aws_iot_shadow_internal_delete_request_json(deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); if ( SUCCESS != rc ) { FUNC_EXIT_RC( rc ); } rc = aws_iot_shadow_internal_action(pThingName, SHADOW_DELETE, deleteRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, timeout_seconds, isPersistentSubscribe); FUNC_EXIT_RC(rc); } IoT_Error_t aws_iot_shadow_get(AWS_IoT_Client *pClient, const char *pThingName, fpActionCallback_t callback, void *pContextData, uint8_t timeout_seconds, bool isPersistentSubscribe) { char getRequestJsonBuf[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; IoT_Error_t rc; FUNC_ENTRY; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } if(!aws_iot_mqtt_is_client_connected(pClient)) { FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); } rc = aws_iot_shadow_internal_get_request_json(getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE ); if (SUCCESS != rc) { FUNC_EXIT_RC(rc); } rc = aws_iot_shadow_internal_action(pThingName, SHADOW_GET, getRequestJsonBuf, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE, callback, pContextData, timeout_seconds, isPersistentSubscribe); FUNC_EXIT_RC(rc); } IoT_Error_t aws_iot_shadow_set_autoreconnect_status(AWS_IoT_Client *pClient, bool newStatus) { return aws_iot_mqtt_autoreconnect_set_status(pClient, newStatus); } #ifdef __cplusplus } #endif