Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
shadow_sample.c
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 00016 /** 00017 * @file shadow_sample.c 00018 * @brief A simple connected window example demonstrating the use of Thing Shadow 00019 */ 00020 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 #include <ctype.h> 00024 #include <unistd.h> 00025 #include <string.h> 00026 #include <limits.h> 00027 00028 #include "aws_iot_config.h" 00029 #include "aws_iot_log.h" 00030 #include "aws_iot_version.h" 00031 #include "aws_iot_mqtt_client_interface.h" 00032 #include "aws_iot_shadow_interface.h" 00033 00034 /*! 00035 * The goal of this sample application is to demonstrate the capabilities of shadow. 00036 * This device(say Connected Window) will open the window of a room based on temperature 00037 * It can report to the Shadow the following parameters: 00038 * 1. temperature of the room (double) 00039 * 2. status of the window (open or close) 00040 * It can act on commands from the cloud. In this case it will open or close the window based on the json object "windowOpen" data[open/close] 00041 * 00042 * The two variables from a device's perspective are double temperature and bool windowOpen 00043 * The device needs to act on only on windowOpen variable, so we will create a primitiveJson_t object with callback 00044 The Json Document in the cloud will be 00045 { 00046 "reported": { 00047 "temperature": 0, 00048 "windowOpen": false 00049 }, 00050 "desired": { 00051 "windowOpen": false 00052 } 00053 } 00054 */ 00055 00056 #define ROOMTEMPERATURE_UPPERLIMIT 32.0f 00057 #define ROOMTEMPERATURE_LOWERLIMIT 25.0f 00058 #define STARTING_ROOMTEMPERATURE ROOMTEMPERATURE_LOWERLIMIT 00059 00060 #define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 00061 00062 static char certDirectory[PATH_MAX + 1] = "../../../certs"; 00063 #define HOST_ADDRESS_SIZE 255 00064 static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST; 00065 static uint32_t port = AWS_IOT_MQTT_PORT; 00066 static uint8_t numPubs = 5; 00067 00068 static void simulateRoomTemperature(float *pRoomTemperature) { 00069 static float deltaChange; 00070 00071 if(*pRoomTemperature >= ROOMTEMPERATURE_UPPERLIMIT) { 00072 deltaChange = -0.5f; 00073 } else if(*pRoomTemperature <= ROOMTEMPERATURE_LOWERLIMIT) { 00074 deltaChange = 0.5f; 00075 } 00076 00077 *pRoomTemperature += deltaChange; 00078 } 00079 00080 void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status, 00081 const char *pReceivedJsonDocument, void *pContextData) { 00082 IOT_UNUSED(pThingName); 00083 IOT_UNUSED(action); 00084 IOT_UNUSED(pReceivedJsonDocument); 00085 IOT_UNUSED(pContextData); 00086 00087 if(SHADOW_ACK_TIMEOUT == status) { 00088 IOT_INFO("Update Timeout--"); 00089 } else if(SHADOW_ACK_REJECTED == status) { 00090 IOT_INFO("Update RejectedXX"); 00091 } else if(SHADOW_ACK_ACCEPTED == status) { 00092 IOT_INFO("Update Accepted !!"); 00093 } 00094 } 00095 00096 void windowActuate_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) { 00097 IOT_UNUSED(pJsonString); 00098 IOT_UNUSED(JsonStringDataLen); 00099 00100 if(pContext != NULL) { 00101 IOT_INFO("Delta - Window state changed to %d", *(bool *) (pContext->pData)); 00102 } 00103 } 00104 00105 void parseInputArgsForConnectParams(int argc, char **argv) { 00106 int opt; 00107 00108 while(-1 != (opt = getopt(argc, argv, "h:p:c:n:"))) { 00109 switch(opt) { 00110 case 'h': 00111 strncpy(HostAddress, optarg, HOST_ADDRESS_SIZE); 00112 IOT_DEBUG("Host %s", optarg); 00113 break; 00114 case 'p': 00115 port = atoi(optarg); 00116 IOT_DEBUG("arg %s", optarg); 00117 break; 00118 case 'c': 00119 strncpy(certDirectory, optarg, PATH_MAX + 1); 00120 IOT_DEBUG("cert root directory %s", optarg); 00121 break; 00122 case 'n': 00123 numPubs = atoi(optarg); 00124 IOT_DEBUG("num pubs %s", optarg); 00125 break; 00126 case '?': 00127 if(optopt == 'c') { 00128 IOT_ERROR("Option -%c requires an argument.", optopt); 00129 } else if(isprint(optopt)) { 00130 IOT_WARN("Unknown option `-%c'.", optopt); 00131 } else { 00132 IOT_WARN("Unknown option character `\\x%x'.", optopt); 00133 } 00134 break; 00135 default: 00136 IOT_ERROR("ERROR in command line argument parsing"); 00137 break; 00138 } 00139 } 00140 00141 } 00142 00143 int main(int argc, char **argv) { 00144 IoT_Error_t rc = FAILURE; 00145 int32_t i = 0; 00146 00147 char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER]; 00148 size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]); 00149 char *pJsonStringToUpdate; 00150 float temperature = 0.0; 00151 00152 bool windowOpen = false; 00153 jsonStruct_t windowActuator; 00154 windowActuator.cb = windowActuate_Callback; 00155 windowActuator.pData = &windowOpen; 00156 windowActuator.dataLength = sizeof(bool); 00157 windowActuator.pKey = "windowOpen"; 00158 windowActuator.type = SHADOW_JSON_BOOL; 00159 00160 jsonStruct_t temperatureHandler; 00161 temperatureHandler.cb = NULL; 00162 temperatureHandler.pKey = "temperature"; 00163 temperatureHandler.pData = &temperature; 00164 temperatureHandler.dataLength = sizeof(float); 00165 temperatureHandler.type = SHADOW_JSON_FLOAT; 00166 00167 char rootCA[PATH_MAX + 1]; 00168 char clientCRT[PATH_MAX + 1]; 00169 char clientKey[PATH_MAX + 1]; 00170 char CurrentWD[PATH_MAX + 1]; 00171 00172 IOT_INFO("\nAWS IoT SDK Version %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); 00173 00174 getcwd(CurrentWD, sizeof(CurrentWD)); 00175 snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME); 00176 snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME); 00177 snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME); 00178 00179 IOT_DEBUG("rootCA %s", rootCA); 00180 IOT_DEBUG("clientCRT %s", clientCRT); 00181 IOT_DEBUG("clientKey %s", clientKey); 00182 00183 parseInputArgsForConnectParams(argc, argv); 00184 00185 // initialize the mqtt client 00186 AWS_IoT_Client mqttClient; 00187 00188 ShadowInitParameters_t sp = ShadowInitParametersDefault; 00189 sp.pHost = AWS_IOT_MQTT_HOST; 00190 sp.port = AWS_IOT_MQTT_PORT; 00191 sp.pClientCRT = clientCRT; 00192 sp.pClientKey = clientKey; 00193 sp.pRootCA = rootCA; 00194 sp.enableAutoReconnect = false; 00195 sp.disconnectHandler = NULL; 00196 00197 IOT_INFO("Shadow Init"); 00198 rc = aws_iot_shadow_init(&mqttClient, &sp); 00199 if(SUCCESS != rc) { 00200 IOT_ERROR("Shadow Connection Error"); 00201 return rc; 00202 } 00203 00204 ShadowConnectParameters_t scp = ShadowConnectParametersDefault; 00205 scp.pMyThingName = AWS_IOT_MY_THING_NAME; 00206 scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID; 00207 scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID); 00208 00209 IOT_INFO("Shadow Connect"); 00210 rc = aws_iot_shadow_connect(&mqttClient, &scp); 00211 if(SUCCESS != rc) { 00212 IOT_ERROR("Shadow Connection Error"); 00213 return rc; 00214 } 00215 00216 /* 00217 * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h 00218 * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 00219 * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 00220 */ 00221 rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true); 00222 if(SUCCESS != rc) { 00223 IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc); 00224 return rc; 00225 } 00226 00227 rc = aws_iot_shadow_register_delta(&mqttClient, &windowActuator); 00228 00229 if(SUCCESS != rc) { 00230 IOT_ERROR("Shadow Register Delta Error"); 00231 } 00232 temperature = STARTING_ROOMTEMPERATURE; 00233 00234 // loop and publish a change in temperature 00235 while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) { 00236 rc = aws_iot_shadow_yield(&mqttClient, 200); 00237 if(NETWORK_ATTEMPTING_RECONNECT == rc) { 00238 sleep(1); 00239 // If the client is attempting to reconnect we will skip the rest of the loop. 00240 continue; 00241 } 00242 IOT_INFO("\n=======================================================================================\n"); 00243 IOT_INFO("On Device: window state %s", windowOpen ? "true" : "false"); 00244 simulateRoomTemperature(&temperature); 00245 00246 rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); 00247 if(SUCCESS == rc) { 00248 rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 2, &temperatureHandler, 00249 &windowActuator); 00250 if(SUCCESS == rc) { 00251 rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer); 00252 if(SUCCESS == rc) { 00253 IOT_INFO("Update Shadow: %s", JsonDocumentBuffer); 00254 rc = aws_iot_shadow_update(&mqttClient, AWS_IOT_MY_THING_NAME, JsonDocumentBuffer, 00255 ShadowUpdateStatusCallback, NULL, 4, true); 00256 } 00257 } 00258 } 00259 IOT_INFO("*****************************************************************************************\n"); 00260 sleep(1); 00261 } 00262 00263 if(SUCCESS != rc) { 00264 IOT_ERROR("An error occurred in the loop %d", rc); 00265 } 00266 00267 IOT_INFO("Disconnecting"); 00268 rc = aws_iot_shadow_disconnect(&mqttClient); 00269 00270 if(SUCCESS != rc) { 00271 IOT_ERROR("Disconnect error %d", rc); 00272 } 00273 00274 return rc; 00275 }
Generated on Tue Jul 12 2022 19:02:38 by
1.7.2