Catie fork

Dependencies:   SDFileSystem X_NUCLEO_IKS01A1

Fork of ATT_AWS_IoT_demo by AT&T IoT

Committer:
ampembeng
Date:
Thu Dec 15 18:05:09 2016 +0000
Revision:
23:b9ff83dc965f
Parent:
20:ee34856ae510
Child:
24:224c07ec3bd0
Added an alternate demo that publishes JSON data to a topic instead of using the device shadow.  The topic (rule) is intended to be used along with DynamoDB and S3 (a static website).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Janos Follath 0:fc70c47eecb4 1 /*
ampembeng 15:6f2798e45099 2 * AT&T IoT Starter Kit example using Amazon Web Service
mbed_official 12:1ae41c231014 3 */
ampembeng 15:6f2798e45099 4 #include "mbed.h"
ampembeng 15:6f2798e45099 5
ampembeng 18:6370da1de572 6 // SD File System
ampembeng 18:6370da1de572 7 #include "SDFileSystem.h"
ampembeng 18:6370da1de572 8
ampembeng 15:6f2798e45099 9 // Serial extension
ampembeng 15:6f2798e45099 10 #include "MODSERIAL.h"
Janos Follath 0:fc70c47eecb4 11
ampembeng 15:6f2798e45099 12 // Network includes
ampembeng 15:6f2798e45099 13 #include "WNCInterface.h"
ampembeng 15:6f2798e45099 14 #include "network_interface.h"
Janos Follath 0:fc70c47eecb4 15
ampembeng 15:6f2798e45099 16 // AWS includes
ampembeng 15:6f2798e45099 17 #include "aws_iot_log.h"
ampembeng 15:6f2798e45099 18 #include "aws_iot_version.h"
ampembeng 15:6f2798e45099 19 #include "aws_iot_shadow_interface.h"
ampembeng 15:6f2798e45099 20 #include "aws_iot_shadow_json_data.h"
ampembeng 15:6f2798e45099 21 #include "aws_iot_config.h"
ampembeng 15:6f2798e45099 22 #include "aws_iot_mqtt_interface.h"
mbed_official 12:1ae41c231014 23
ampembeng 20:ee34856ae510 24 // Sensors
ampembeng 20:ee34856ae510 25 #include "HTS221.h"
ampembeng 20:ee34856ae510 26
Janos Follath 0:fc70c47eecb4 27 #if DEBUG_LEVEL > 0
Janos Follath 0:fc70c47eecb4 28 #include "mbedtls/debug.h"
Janos Follath 0:fc70c47eecb4 29 #endif
Janos Follath 0:fc70c47eecb4 30
ampembeng 15:6f2798e45099 31 //=====================================================================================================================
ampembeng 15:6f2798e45099 32 //
ampembeng 15:6f2798e45099 33 // Defines
ampembeng 15:6f2798e45099 34 //
ampembeng 15:6f2798e45099 35 //=====================================================================================================================
ampembeng 15:6f2798e45099 36 // LED Colors
ampembeng 15:6f2798e45099 37 #define COLOR_OFF 0x00
ampembeng 15:6f2798e45099 38 #define COLOR_RED 0x01
ampembeng 15:6f2798e45099 39 #define COLOR_GREEN 0x02
ampembeng 15:6f2798e45099 40 #define COLOR_BLUE 0x04
ampembeng 15:6f2798e45099 41 #define COLOR_WHITE 0x07
ampembeng 15:6f2798e45099 42 #define NUM_COLORS 5
Janos Follath 0:fc70c47eecb4 43
ampembeng 15:6f2798e45099 44 // AWS defines
ampembeng 18:6370da1de572 45 #define PATH_MAX 1024
ampembeng 15:6f2798e45099 46 #define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 // NOTE: Be wary of this if your JSON doc grows
ampembeng 15:6f2798e45099 47 #define SHADOW_SYNC_INTERVAL 3.0 // How often we sync with AWS Shadow (in seconds)
Janos Follath 0:fc70c47eecb4 48
ampembeng 15:6f2798e45099 49 // Comment out the following line if color is not supported on the terminal
ampembeng 15:6f2798e45099 50 //#define USE_COLOR
ampembeng 15:6f2798e45099 51 #ifdef USE_COLOR
ampembeng 15:6f2798e45099 52 #define BLK "\033[30m"
ampembeng 15:6f2798e45099 53 #define RED "\033[31m"
ampembeng 15:6f2798e45099 54 #define GRN "\033[32m"
ampembeng 15:6f2798e45099 55 #define YEL "\033[33m"
ampembeng 15:6f2798e45099 56 #define BLU "\033[34m"
ampembeng 15:6f2798e45099 57 #define MAG "\033[35m"
ampembeng 15:6f2798e45099 58 #define CYN "\033[36m"
ampembeng 15:6f2798e45099 59 #define WHT "\033[37m"
ampembeng 15:6f2798e45099 60 #define DEF "\033[39m"
ampembeng 15:6f2798e45099 61 #else
ampembeng 15:6f2798e45099 62 #define BLK
ampembeng 15:6f2798e45099 63 #define RED
ampembeng 15:6f2798e45099 64 #define GRN
ampembeng 15:6f2798e45099 65 #define YEL
ampembeng 15:6f2798e45099 66 #define BLU
ampembeng 15:6f2798e45099 67 #define MAG
ampembeng 15:6f2798e45099 68 #define CYN
ampembeng 15:6f2798e45099 69 #define WHT
ampembeng 15:6f2798e45099 70 #define DEF
Janos Follath 0:fc70c47eecb4 71 #endif
Janos Follath 0:fc70c47eecb4 72
ampembeng 20:ee34856ae510 73 // Sensor defines
ampembeng 20:ee34856ae510 74 #define CTOF(x) ((x)*1.8+32) // Temperature
ampembeng 20:ee34856ae510 75
ampembeng 15:6f2798e45099 76 //=====================================================================================================================
ampembeng 15:6f2798e45099 77 //
ampembeng 15:6f2798e45099 78 // Globals
ampembeng 15:6f2798e45099 79 //
ampembeng 15:6f2798e45099 80 //=====================================================================================================================
ampembeng 15:6f2798e45099 81 // Controls LED color
ampembeng 15:6f2798e45099 82 unsigned char ledColor = COLOR_OFF;
ampembeng 15:6f2798e45099 83
ampembeng 15:6f2798e45099 84 // Color cycle array (used with SW3 button presses)
ampembeng 15:6f2798e45099 85 unsigned char colorCycle[NUM_COLORS] = {COLOR_OFF, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_WHITE};
Janos Follath 0:fc70c47eecb4 86
ampembeng 15:6f2798e45099 87 // Button interrupts
ampembeng 15:6f2798e45099 88 bool buttonOverride = false;
ampembeng 15:6f2798e45099 89 InterruptIn Interrupt(SW3);
ampembeng 15:6f2798e45099 90
ampembeng 18:6370da1de572 91 // These defines are pulled from aws_iot_config.h
ampembeng 15:6f2798e45099 92 char HostAddress[255] = AWS_IOT_MQTT_HOST;
ampembeng 18:6370da1de572 93 char MqttClientID[32] = AWS_IOT_MQTT_CLIENT_ID;
ampembeng 18:6370da1de572 94 char ThingName[32] = AWS_IOT_MY_THING_NAME;
ampembeng 18:6370da1de572 95 char PortString[5] = "8883";
ampembeng 15:6f2798e45099 96 uint32_t port = AWS_IOT_MQTT_PORT;
ampembeng 23:b9ff83dc965f 97 char iccidName[21] = "12345678901234567890";
Janos Follath 0:fc70c47eecb4 98
ampembeng 20:ee34856ae510 99 // Sensor data
ampembeng 20:ee34856ae510 100 float temperature = 0.0;
ampembeng 20:ee34856ae510 101 int humidity = 0;
ampembeng 20:ee34856ae510 102
ampembeng 23:b9ff83dc965f 103 // Temp/humidity object
ampembeng 23:b9ff83dc965f 104 HTS221 hts221;
ampembeng 23:b9ff83dc965f 105
ampembeng 15:6f2798e45099 106 //=====================================================================================================================
ampembeng 15:6f2798e45099 107 //
ampembeng 15:6f2798e45099 108 // Devices
ampembeng 15:6f2798e45099 109 //
ampembeng 15:6f2798e45099 110 //=====================================================================================================================
ampembeng 15:6f2798e45099 111 // GPIOs for RGB LED
ampembeng 15:6f2798e45099 112 DigitalOut led_green(LED_GREEN);
ampembeng 15:6f2798e45099 113 DigitalOut led_red(LED_RED);
ampembeng 15:6f2798e45099 114 DigitalOut led_blue(LED_BLUE);
Janos Follath 0:fc70c47eecb4 115
ampembeng 15:6f2798e45099 116 // USB Serial port (to PC)
ampembeng 15:6f2798e45099 117 MODSERIAL pc(USBTX,USBRX,256,256);
Janos Follath 0:fc70c47eecb4 118
ampembeng 18:6370da1de572 119 // SD card access (MOSI, MISO, SCK, CS)
ampembeng 18:6370da1de572 120 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");
ampembeng 18:6370da1de572 121
ampembeng 20:ee34856ae510 122 // I2C bus (SDA, SCL)
ampembeng 20:ee34856ae510 123 I2C i2c(PTC11, PTC10);
ampembeng 20:ee34856ae510 124
ampembeng 15:6f2798e45099 125 //=====================================================================================================================
ampembeng 15:6f2798e45099 126 //
ampembeng 15:6f2798e45099 127 // Functions
ampembeng 15:6f2798e45099 128 //
ampembeng 15:6f2798e45099 129 //=====================================================================================================================
ampembeng 15:6f2798e45099 130 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 131 //* Prints the given format to the PC serial port. Exposed to all files via aws_iot_log.h
ampembeng 15:6f2798e45099 132 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 133 void pc_print(const char * format, ...)
ampembeng 15:6f2798e45099 134 {
ampembeng 15:6f2798e45099 135 va_list vl;
ampembeng 15:6f2798e45099 136 va_start(vl, format);
ampembeng 15:6f2798e45099 137 pc.vprintf(format, vl);
ampembeng 15:6f2798e45099 138 va_end(vl);
ampembeng 15:6f2798e45099 139 }
Janos Follath 0:fc70c47eecb4 140
ampembeng 15:6f2798e45099 141 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 142 //* Set the RGB LED's Color
ampembeng 15:6f2798e45099 143 //* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue)
ampembeng 15:6f2798e45099 144 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 145 void SetLedColor(unsigned char ucColor)
ampembeng 18:6370da1de572 146 {
ampembeng 15:6f2798e45099 147 //Note that when an LED is on, you write a 0 to it:
ampembeng 15:6f2798e45099 148 led_red = !(ucColor & 0x1); //bit 0
ampembeng 15:6f2798e45099 149 led_green = !(ucColor & 0x2); //bit 1
ampembeng 15:6f2798e45099 150 led_blue = !(ucColor & 0x4); //bit 2
ampembeng 15:6f2798e45099 151 }
Janos Follath 0:fc70c47eecb4 152
ampembeng 15:6f2798e45099 153 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 154 //* SW3 Button handler. Finds the current LED color and sets the button to the next color in colorCycle[]
ampembeng 15:6f2798e45099 155 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 156 void sw3ButtonHandler()
ampembeng 15:6f2798e45099 157 {
ampembeng 15:6f2798e45099 158 int i;
ampembeng 15:6f2798e45099 159 for(i=0; i < NUM_COLORS; i++) {
ampembeng 15:6f2798e45099 160 if (ledColor == colorCycle[i])
ampembeng 15:6f2798e45099 161 break;
ampembeng 15:6f2798e45099 162 }
ampembeng 15:6f2798e45099 163
ampembeng 15:6f2798e45099 164 // (circular-queue)
ampembeng 15:6f2798e45099 165 if (++i == NUM_COLORS)
ampembeng 15:6f2798e45099 166 i = 0;
ampembeng 15:6f2798e45099 167
ampembeng 15:6f2798e45099 168 ledColor = colorCycle[i];
ampembeng 15:6f2798e45099 169 SetLedColor(ledColor);
ampembeng 15:6f2798e45099 170 buttonOverride = true;
ampembeng 15:6f2798e45099 171 }
Janos Follath 0:fc70c47eecb4 172
ampembeng 23:b9ff83dc965f 173 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 174 //* Print LED and sensor data
ampembeng 23:b9ff83dc965f 175 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 176 void printData()
ampembeng 23:b9ff83dc965f 177 {
ampembeng 23:b9ff83dc965f 178 INFO("Temperature is: %0.2f F", temperature);
ampembeng 23:b9ff83dc965f 179 INFO("Humidity is: %02d", humidity);
ampembeng 23:b9ff83dc965f 180 switch (ledColor) {
ampembeng 23:b9ff83dc965f 181 case COLOR_OFF:
ampembeng 23:b9ff83dc965f 182 INFO("LED: Off");
ampembeng 23:b9ff83dc965f 183 break;
ampembeng 23:b9ff83dc965f 184 case COLOR_RED:
ampembeng 23:b9ff83dc965f 185 INFO("LED: Red");
ampembeng 23:b9ff83dc965f 186 break;
ampembeng 23:b9ff83dc965f 187 case COLOR_GREEN:
ampembeng 23:b9ff83dc965f 188 INFO("LED: Green");
ampembeng 23:b9ff83dc965f 189 break;
ampembeng 23:b9ff83dc965f 190 case COLOR_BLUE:
ampembeng 23:b9ff83dc965f 191 INFO("LED: Blue");
ampembeng 23:b9ff83dc965f 192 break;
ampembeng 23:b9ff83dc965f 193 case COLOR_WHITE:
ampembeng 23:b9ff83dc965f 194 INFO("LED: White");
ampembeng 23:b9ff83dc965f 195 break;
ampembeng 23:b9ff83dc965f 196 }
ampembeng 23:b9ff83dc965f 197 }
ampembeng 23:b9ff83dc965f 198
ampembeng 15:6f2798e45099 199 //=====================================================================================================================
ampembeng 15:6f2798e45099 200 //
ampembeng 15:6f2798e45099 201 // AWS Shadow Callbacks
ampembeng 15:6f2798e45099 202 //
ampembeng 15:6f2798e45099 203 //=====================================================================================================================
ampembeng 15:6f2798e45099 204 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 205 //* This is the callback function that fires when an update is sent. It will print the update response status.
ampembeng 15:6f2798e45099 206 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 207 void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
ampembeng 15:6f2798e45099 208 const char *pReceivedJsonDocument, void *pContextData) {
Janos Follath 0:fc70c47eecb4 209
ampembeng 15:6f2798e45099 210 INFO("Shadow Update Status Callback");
ampembeng 15:6f2798e45099 211
ampembeng 15:6f2798e45099 212 if (status == SHADOW_ACK_TIMEOUT) {
ampembeng 15:6f2798e45099 213 INFO("Update Timeout--");
ampembeng 15:6f2798e45099 214 } else if (status == SHADOW_ACK_REJECTED) {
ampembeng 15:6f2798e45099 215 INFO("Update RejectedXX");
ampembeng 15:6f2798e45099 216 } else if (status == SHADOW_ACK_ACCEPTED) {
ampembeng 15:6f2798e45099 217 INFO("Update Accepted!!"); // Good
ampembeng 15:6f2798e45099 218 }
ampembeng 15:6f2798e45099 219 }
Janos Follath 0:fc70c47eecb4 220
ampembeng 15:6f2798e45099 221 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 222 //* This is the callback function that fires when AWS has sends out a shadow update.
ampembeng 15:6f2798e45099 223 //*********************************************************************************************************************
ampembeng 15:6f2798e45099 224 void ledControl_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
ampembeng 15:6f2798e45099 225
ampembeng 15:6f2798e45099 226 INFO("LED Callback Detected.");
ampembeng 15:6f2798e45099 227
ampembeng 15:6f2798e45099 228 if (pContext != NULL) {
ampembeng 15:6f2798e45099 229 switch (*(unsigned char *)(pContext->pData)){
ampembeng 15:6f2798e45099 230 case COLOR_OFF:
ampembeng 15:6f2798e45099 231 INFO("LED -> OFF (%d)", *(unsigned char *)(pContext->pData));
ampembeng 15:6f2798e45099 232 break;
ampembeng 15:6f2798e45099 233 case COLOR_RED:
ampembeng 15:6f2798e45099 234 INFO("LED -> RED (%d)", *(unsigned char *)(pContext->pData));
ampembeng 15:6f2798e45099 235 break;
ampembeng 15:6f2798e45099 236 case COLOR_GREEN:
ampembeng 15:6f2798e45099 237 INFO("LED -> GREEN (%d)", *(unsigned char *)(pContext->pData));
ampembeng 15:6f2798e45099 238 break;
ampembeng 15:6f2798e45099 239 case COLOR_BLUE:
ampembeng 15:6f2798e45099 240 INFO("LED -> BLUE (%d)", *(unsigned char *)(pContext->pData));
ampembeng 15:6f2798e45099 241 break;
ampembeng 15:6f2798e45099 242 case COLOR_WHITE:
ampembeng 15:6f2798e45099 243 INFO("LED -> WHITE (%d)", *(unsigned char *)(pContext->pData));
ampembeng 15:6f2798e45099 244 break;
Janos Follath 0:fc70c47eecb4 245 }
ampembeng 15:6f2798e45099 246 }
ampembeng 15:6f2798e45099 247 else {
ampembeng 15:6f2798e45099 248 INFO("pContext was detected as NULL");
Janos Follath 0:fc70c47eecb4 249 }
ampembeng 15:6f2798e45099 250 }
ampembeng 23:b9ff83dc965f 251
ampembeng 23:b9ff83dc965f 252 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 253 //* Subscribe callback (used with alternate demo)
ampembeng 23:b9ff83dc965f 254 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 255 int MQTTcallbackHandler(MQTTCallbackParams params) {
ampembeng 23:b9ff83dc965f 256
ampembeng 23:b9ff83dc965f 257 INFO("Subscribe callback");
ampembeng 23:b9ff83dc965f 258 INFO("%.*s\t%.*s",
ampembeng 23:b9ff83dc965f 259 (int)params.TopicNameLen, params.pTopicName,
ampembeng 23:b9ff83dc965f 260 (int)params.MessageParams.PayloadLen, (char*)params.MessageParams.pPayload);
ampembeng 23:b9ff83dc965f 261
ampembeng 23:b9ff83dc965f 262 return 0;
ampembeng 23:b9ff83dc965f 263 }
ampembeng 23:b9ff83dc965f 264
ampembeng 23:b9ff83dc965f 265 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 266 //* Disconnect handling (used with alternate demo)
ampembeng 23:b9ff83dc965f 267 //*********************************************************************************************************************
ampembeng 23:b9ff83dc965f 268 void disconnectCallbackHandler(void) {
ampembeng 23:b9ff83dc965f 269 WARN("MQTT Disconnect");
ampembeng 23:b9ff83dc965f 270 IoT_Error_t rc = NONE_ERROR;
ampembeng 23:b9ff83dc965f 271 if(aws_iot_is_autoreconnect_enabled()){
ampembeng 23:b9ff83dc965f 272 INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
ampembeng 23:b9ff83dc965f 273 }else{
ampembeng 23:b9ff83dc965f 274 WARN("Auto Reconnect not enabled. Starting manual reconnect...");
ampembeng 23:b9ff83dc965f 275 rc = aws_iot_mqtt_attempt_reconnect();
ampembeng 23:b9ff83dc965f 276 if(RECONNECT_SUCCESSFUL == rc){
ampembeng 23:b9ff83dc965f 277 WARN("Manual Reconnect Successful");
ampembeng 23:b9ff83dc965f 278 }else{
ampembeng 23:b9ff83dc965f 279 WARN("Manual Reconnect Failed - %d", rc);
ampembeng 23:b9ff83dc965f 280 }
ampembeng 23:b9ff83dc965f 281 }
ampembeng 23:b9ff83dc965f 282 }
ampembeng 23:b9ff83dc965f 283
ampembeng 23:b9ff83dc965f 284 //=====================================================================================================================
ampembeng 23:b9ff83dc965f 285 //
ampembeng 23:b9ff83dc965f 286 // Out-of-Box Demo: This function is used as part of the binary that comes with the Starter Kit. Instead of using an
ampembeng 23:b9ff83dc965f 287 // AWS device shadow, it publishes to an AWS Rule. The Rule is setup to store data to a DynamoDB, and
ampembeng 23:b9ff83dc965f 288 // the demo S3 website pulls that data from the DynamoDB and displays it.
ampembeng 23:b9ff83dc965f 289 //
ampembeng 23:b9ff83dc965f 290 //=====================================================================================================================
ampembeng 23:b9ff83dc965f 291 int outOfBoxDemo() {
ampembeng 23:b9ff83dc965f 292 INFO("Running Out-of-Box Function (alternate demo).");
ampembeng 23:b9ff83dc965f 293
ampembeng 23:b9ff83dc965f 294 IoT_Error_t rc = NONE_ERROR;
ampembeng 23:b9ff83dc965f 295 int32_t i = 0;
ampembeng 23:b9ff83dc965f 296 int publishCount = 0;
ampembeng 23:b9ff83dc965f 297 bool infinitePublishFlag = true;
ampembeng 23:b9ff83dc965f 298 char cPayload[100];
ampembeng 23:b9ff83dc965f 299 char cTopic[100];
ampembeng 23:b9ff83dc965f 300 const string colorStrings[] = {"Off", "Red", "Green", "", "Blue", "", "", "White"};
ampembeng 23:b9ff83dc965f 301 float updateInterval = 5.0; // seconds
ampembeng 23:b9ff83dc965f 302
ampembeng 23:b9ff83dc965f 303 MQTTConnectParams connectParams = MQTTConnectParamsDefault;
ampembeng 23:b9ff83dc965f 304 connectParams.KeepAliveInterval_sec = 10;
ampembeng 23:b9ff83dc965f 305 connectParams.isCleansession = true;
ampembeng 23:b9ff83dc965f 306 connectParams.MQTTVersion = MQTT_3_1_1;
ampembeng 23:b9ff83dc965f 307 connectParams.pClientID = iccidName; // Using ICCID for unique Client ID
ampembeng 23:b9ff83dc965f 308 connectParams.pHostURL = HostAddress;
ampembeng 23:b9ff83dc965f 309 connectParams.port = port;
ampembeng 23:b9ff83dc965f 310 connectParams.isWillMsgPresent = false;
ampembeng 23:b9ff83dc965f 311 connectParams.pRootCALocation = AWS_IOT_ROOT_CA_FILENAME;
ampembeng 23:b9ff83dc965f 312 connectParams.pDeviceCertLocation = AWS_IOT_CERTIFICATE_FILENAME;
ampembeng 23:b9ff83dc965f 313 connectParams.pDevicePrivateKeyLocation = AWS_IOT_PRIVATE_KEY_FILENAME;
ampembeng 23:b9ff83dc965f 314 connectParams.mqttCommandTimeout_ms = 10000;
ampembeng 23:b9ff83dc965f 315 connectParams.tlsHandshakeTimeout_ms = 10000;
ampembeng 23:b9ff83dc965f 316 connectParams.isSSLHostnameVerify = true; // ensure this is set to true for production
ampembeng 23:b9ff83dc965f 317 connectParams.disconnectHandler = disconnectCallbackHandler;
ampembeng 23:b9ff83dc965f 318
ampembeng 23:b9ff83dc965f 319 INFO("Connecting...");
ampembeng 23:b9ff83dc965f 320 rc = aws_iot_mqtt_connect(&connectParams);
ampembeng 23:b9ff83dc965f 321 if (NONE_ERROR != rc) {
ampembeng 23:b9ff83dc965f 322 ERROR("Error(%d) connecting to %s:%d", rc, connectParams.pHostURL, connectParams.port);
ampembeng 23:b9ff83dc965f 323 }
ampembeng 23:b9ff83dc965f 324
ampembeng 23:b9ff83dc965f 325 /*
ampembeng 23:b9ff83dc965f 326 * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
ampembeng 23:b9ff83dc965f 327 * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
ampembeng 23:b9ff83dc965f 328 * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
ampembeng 23:b9ff83dc965f 329 */
ampembeng 23:b9ff83dc965f 330 INFO("Set Auto Reconnect...");
ampembeng 23:b9ff83dc965f 331 rc = aws_iot_mqtt_autoreconnect_set_status(true);
ampembeng 23:b9ff83dc965f 332 if (NONE_ERROR != rc) {
ampembeng 23:b9ff83dc965f 333 ERROR("Unable to set Auto Reconnect to true - %d", rc);
ampembeng 23:b9ff83dc965f 334 return rc;
ampembeng 23:b9ff83dc965f 335 }
ampembeng 23:b9ff83dc965f 336
ampembeng 23:b9ff83dc965f 337 // Comment this in if you want to subscribe
ampembeng 23:b9ff83dc965f 338 /*MQTTSubscribeParams subParams = MQTTSubscribeParamsDefault;
ampembeng 23:b9ff83dc965f 339 subParams.mHandler = MQTTcallbackHandler;
ampembeng 23:b9ff83dc965f 340 subParams.pTopic = "sdkTest/sub";
ampembeng 23:b9ff83dc965f 341 subParams.qos = QOS_0;
ampembeng 23:b9ff83dc965f 342
ampembeng 23:b9ff83dc965f 343 if (NONE_ERROR == rc) {
ampembeng 23:b9ff83dc965f 344 INFO("Subscribing...");
ampembeng 23:b9ff83dc965f 345 rc = aws_iot_mqtt_subscribe(&subParams);
ampembeng 23:b9ff83dc965f 346 if (NONE_ERROR != rc) {
ampembeng 23:b9ff83dc965f 347 ERROR("Error subscribing");
ampembeng 23:b9ff83dc965f 348 }
ampembeng 23:b9ff83dc965f 349 }*/
ampembeng 23:b9ff83dc965f 350
ampembeng 23:b9ff83dc965f 351 // Initializ the payload
ampembeng 23:b9ff83dc965f 352 MQTTMessageParams Msg = MQTTMessageParamsDefault;
ampembeng 23:b9ff83dc965f 353 Msg.qos = QOS_0;
ampembeng 23:b9ff83dc965f 354 Msg.pPayload = (void *) cPayload;
ampembeng 23:b9ff83dc965f 355
ampembeng 23:b9ff83dc965f 356 MQTTPublishParams Params = MQTTPublishParamsDefault;
ampembeng 23:b9ff83dc965f 357
ampembeng 23:b9ff83dc965f 358 // Sets up the topic to publish to
ampembeng 23:b9ff83dc965f 359 sprintf(cTopic, AWS_IOT_MY_TOPIC, iccidName);
ampembeng 23:b9ff83dc965f 360 Params.pTopic = cTopic;
ampembeng 23:b9ff83dc965f 361
ampembeng 23:b9ff83dc965f 362 if (publishCount != 0) {
ampembeng 23:b9ff83dc965f 363 infinitePublishFlag = false;
ampembeng 23:b9ff83dc965f 364 }
ampembeng 23:b9ff83dc965f 365
ampembeng 23:b9ff83dc965f 366 INFO("READY TO PUBLISH! Press SW3 button to publish current data.");
ampembeng 23:b9ff83dc965f 367 while ((NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc)
ampembeng 23:b9ff83dc965f 368 && (publishCount > 0 || infinitePublishFlag)) {
ampembeng 23:b9ff83dc965f 369
ampembeng 23:b9ff83dc965f 370 // Max time the yield function will wait for read messages
ampembeng 23:b9ff83dc965f 371 rc = aws_iot_mqtt_yield(100);
ampembeng 23:b9ff83dc965f 372 if(NETWORK_ATTEMPTING_RECONNECT == rc){
ampembeng 23:b9ff83dc965f 373 INFO("--> sleep (attempting to reconnect)");
ampembeng 23:b9ff83dc965f 374 wait(1);
ampembeng 23:b9ff83dc965f 375 // If the client is attempting to reconnect we will skip the rest of the loop.
ampembeng 23:b9ff83dc965f 376 continue;
ampembeng 23:b9ff83dc965f 377 }
ampembeng 23:b9ff83dc965f 378
ampembeng 23:b9ff83dc965f 379 // Whenever the software button (SW3) is pressed the LED will changes color and this will
ampembeng 23:b9ff83dc965f 380 // trigger a publish to the AWS topic specified.
ampembeng 23:b9ff83dc965f 381 if (buttonOverride) {
ampembeng 23:b9ff83dc965f 382 buttonOverride = false;
ampembeng 23:b9ff83dc965f 383
ampembeng 23:b9ff83dc965f 384 // Get temp/humidity values
ampembeng 23:b9ff83dc965f 385 temperature = CTOF(hts221.readTemperature());
ampembeng 23:b9ff83dc965f 386 humidity = hts221.readHumidity();
ampembeng 23:b9ff83dc965f 387
ampembeng 23:b9ff83dc965f 388 // Loading data into JSON format
ampembeng 23:b9ff83dc965f 389 sprintf(cPayload, "{\"color\":\"%s\",\"temperature\":%f,\"humidity\":%d}", colorStrings[ledColor], temperature, humidity);
ampembeng 23:b9ff83dc965f 390 Msg.PayloadLen = strlen(cPayload) + 1;
ampembeng 23:b9ff83dc965f 391 Params.MessageParams = Msg;
ampembeng 23:b9ff83dc965f 392
ampembeng 23:b9ff83dc965f 393 // Publish
ampembeng 23:b9ff83dc965f 394 rc = aws_iot_mqtt_publish(&Params);
ampembeng 23:b9ff83dc965f 395 if (publishCount > 0) {
ampembeng 23:b9ff83dc965f 396 publishCount--;
ampembeng 23:b9ff83dc965f 397 }
ampembeng 23:b9ff83dc965f 398
ampembeng 23:b9ff83dc965f 399 printData();
ampembeng 23:b9ff83dc965f 400 INFO("--> Update sent. Sleep for %f seconds", updateInterval);
ampembeng 23:b9ff83dc965f 401 wait(updateInterval-.02);
ampembeng 23:b9ff83dc965f 402 }
ampembeng 23:b9ff83dc965f 403 else {
ampembeng 23:b9ff83dc965f 404 wait(.3); // 300 ms
ampembeng 23:b9ff83dc965f 405 }
ampembeng 23:b9ff83dc965f 406 }
ampembeng 23:b9ff83dc965f 407
ampembeng 23:b9ff83dc965f 408 if (NONE_ERROR != rc) {
ampembeng 23:b9ff83dc965f 409 ERROR("An error occurred in the loop.\n");
ampembeng 23:b9ff83dc965f 410 } else {
ampembeng 23:b9ff83dc965f 411 INFO("Publish done\n");
ampembeng 23:b9ff83dc965f 412 }
ampembeng 23:b9ff83dc965f 413
ampembeng 23:b9ff83dc965f 414 return rc;
ampembeng 23:b9ff83dc965f 415 }
ampembeng 15:6f2798e45099 416
ampembeng 15:6f2798e45099 417 //=====================================================================================================================
ampembeng 15:6f2798e45099 418 //
ampembeng 15:6f2798e45099 419 // Main
ampembeng 15:6f2798e45099 420 //
ampembeng 15:6f2798e45099 421 //=====================================================================================================================
ampembeng 15:6f2798e45099 422 int main() {
ampembeng 15:6f2798e45099 423
ampembeng 15:6f2798e45099 424 // Set baud rate for PC Serial
ampembeng 15:6f2798e45099 425 pc.baud(115200);
ampembeng 15:6f2798e45099 426 INFO("Hello World from AT&T IoT Start Kit demo!");
ampembeng 20:ee34856ae510 427
ampembeng 20:ee34856ae510 428 int i;
ampembeng 23:b9ff83dc965f 429 IoT_Error_t rc = NONE_ERROR;
ampembeng 15:6f2798e45099 430 char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
ampembeng 15:6f2798e45099 431 size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
ampembeng 15:6f2798e45099 432
ampembeng 15:6f2798e45099 433 // JSON struct for LED control
ampembeng 15:6f2798e45099 434 jsonStruct_t ledController;
ampembeng 15:6f2798e45099 435 ledController.cb = ledControl_Callback;
ampembeng 15:6f2798e45099 436 ledController.pData = &ledColor;
ampembeng 15:6f2798e45099 437 ledController.pKey = "ledColor";
ampembeng 15:6f2798e45099 438 ledController.type = SHADOW_JSON_UINT8;
ampembeng 15:6f2798e45099 439
ampembeng 20:ee34856ae510 440 // JSON struct for temperature\humidity readings
ampembeng 15:6f2798e45099 441 jsonStruct_t temperatureHandler;
ampembeng 15:6f2798e45099 442 temperatureHandler.cb = NULL;
ampembeng 15:6f2798e45099 443 temperatureHandler.pKey = "temperature";
ampembeng 15:6f2798e45099 444 temperatureHandler.pData = &temperature;
ampembeng 15:6f2798e45099 445 temperatureHandler.type = SHADOW_JSON_FLOAT;
ampembeng 20:ee34856ae510 446
ampembeng 20:ee34856ae510 447 jsonStruct_t humidityHandler;
ampembeng 20:ee34856ae510 448 humidityHandler.cb = NULL;
ampembeng 20:ee34856ae510 449 humidityHandler.pKey = "humidity";
ampembeng 20:ee34856ae510 450 humidityHandler.pData = &humidity;
ampembeng 20:ee34856ae510 451 humidityHandler.type = SHADOW_JSON_INT16;
ampembeng 15:6f2798e45099 452
ampembeng 15:6f2798e45099 453 INFO("AWS IoT SDK Version(dev) %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
ampembeng 15:6f2798e45099 454
ampembeng 18:6370da1de572 455 #ifdef USING_SD_CARD
ampembeng 18:6370da1de572 456 // Paths for certs from SD card
ampembeng 18:6370da1de572 457 INFO("Using SD card files for AWS config.");
ampembeng 18:6370da1de572 458 DEBUG("- mqtt config path: %s", AWS_MQTT_CONFIG_FILENAME);
ampembeng 18:6370da1de572 459 DEBUG("- rootCA path: %s", AWS_IOT_ROOT_CA_FILENAME);
ampembeng 18:6370da1de572 460 DEBUG("- clientCRT path: %s", AWS_IOT_CERTIFICATE_FILENAME);
ampembeng 18:6370da1de572 461 DEBUG("- clientKey path: %s", AWS_IOT_PRIVATE_KEY_FILENAME);
ampembeng 18:6370da1de572 462 #else
ampembeng 18:6370da1de572 463 INFO("Using #defines in aws_iot_config.h and certs from certs.cpp for AWS config.");
ampembeng 18:6370da1de572 464 #endif
ampembeng 15:6f2798e45099 465
ampembeng 16:02008a2a2569 466 // Startup signal - blinks through RGBW then turns off
ampembeng 15:6f2798e45099 467 SetLedColor(COLOR_RED);
ampembeng 15:6f2798e45099 468 wait(.5);
ampembeng 15:6f2798e45099 469 SetLedColor(COLOR_GREEN);
ampembeng 15:6f2798e45099 470 wait(.5);
ampembeng 15:6f2798e45099 471 SetLedColor(COLOR_BLUE);
ampembeng 15:6f2798e45099 472 wait(.5);
ampembeng 16:02008a2a2569 473 SetLedColor(COLOR_WHITE);
ampembeng 16:02008a2a2569 474 wait(.5);
ampembeng 16:02008a2a2569 475 SetLedColor(COLOR_OFF);
ampembeng 20:ee34856ae510 476
ampembeng 20:ee34856ae510 477 // Initialize sensors
ampembeng 23:b9ff83dc965f 478 INFO("Init sensors...");
ampembeng 20:ee34856ae510 479 void hts221_init(void);
ampembeng 20:ee34856ae510 480 i = hts221.begin();
ampembeng 20:ee34856ae510 481 if(!i) {
ampembeng 20:ee34856ae510 482 WARN(RED "HTS221 NOT DETECTED!!\n\r");
ampembeng 20:ee34856ae510 483 }
ampembeng 18:6370da1de572 484
ampembeng 15:6f2798e45099 485 // Setup SW3 button to falling edge interrupt
ampembeng 23:b9ff83dc965f 486 INFO("Init interrupts...");
ampembeng 15:6f2798e45099 487 Interrupt.fall(&sw3ButtonHandler);
ampembeng 15:6f2798e45099 488
ampembeng 15:6f2798e45099 489 // Boot the Avnet Shield before any other operations
ampembeng 23:b9ff83dc965f 490 INFO("Net Boot...");
ampembeng 15:6f2798e45099 491 net_modem_boot();
ampembeng 23:b9ff83dc965f 492
ampembeng 23:b9ff83dc965f 493 //==========================================================================
ampembeng 23:b9ff83dc965f 494 // NOTE: You can comment in the following line for an alternate demo that
ampembeng 23:b9ff83dc965f 495 // is used as the out-of-box demo binary that comes with the AT&T IoT
ampembeng 23:b9ff83dc965f 496 // Starter Kit. It loops instead of the rest of Main()
ampembeng 23:b9ff83dc965f 497 //return outOfBoxDemo();
ampembeng 23:b9ff83dc965f 498 //==========================================================================
ampembeng 23:b9ff83dc965f 499
ampembeng 18:6370da1de572 500 // Intialize MQTT/Cert parameters
ampembeng 15:6f2798e45099 501 ShadowParameters_t sp = ShadowParametersDefault;
ampembeng 18:6370da1de572 502 #ifdef USING_SD_CARD
ampembeng 18:6370da1de572 503 rc = (IoT_Error_t)mbedtls_mqtt_config_parse_file(&sp, AWS_MQTT_CONFIG_FILENAME);
ampembeng 18:6370da1de572 504 if (NONE_ERROR != rc) {
ampembeng 18:6370da1de572 505 ERROR("Failed to initialize mqtt parameters %d", rc);
ampembeng 18:6370da1de572 506 return rc;
ampembeng 18:6370da1de572 507 }
ampembeng 18:6370da1de572 508 sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
ampembeng 18:6370da1de572 509 sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
ampembeng 18:6370da1de572 510 sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
ampembeng 18:6370da1de572 511 #else
ampembeng 15:6f2798e45099 512 sp.pMyThingName = AWS_IOT_MY_THING_NAME;
ampembeng 15:6f2798e45099 513 sp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
ampembeng 15:6f2798e45099 514 sp.pHost = HostAddress;
ampembeng 15:6f2798e45099 515 sp.port = port;
ampembeng 23:b9ff83dc965f 516
ampembeng 23:b9ff83dc965f 517 sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
ampembeng 23:b9ff83dc965f 518 sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
ampembeng 23:b9ff83dc965f 519 sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
ampembeng 18:6370da1de572 520 #endif
ampembeng 20:ee34856ae510 521
ampembeng 18:6370da1de572 522 INFO("Initialize the MQTT client...");
ampembeng 18:6370da1de572 523 MQTTClient_t mqttClient;
ampembeng 18:6370da1de572 524 aws_iot_mqtt_init(&mqttClient);
ampembeng 15:6f2798e45099 525
ampembeng 15:6f2798e45099 526 INFO("Shadow Init...");
ampembeng 15:6f2798e45099 527 rc = aws_iot_shadow_init(&mqttClient);
ampembeng 15:6f2798e45099 528 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 529 ERROR("Shadow Init Error %d", rc);
ampembeng 15:6f2798e45099 530 return rc;
Janos Follath 0:fc70c47eecb4 531 }
ampembeng 15:6f2798e45099 532
ampembeng 15:6f2798e45099 533 INFO("Shadow Connect...");
ampembeng 15:6f2798e45099 534 rc = aws_iot_shadow_connect(&mqttClient, &sp);
ampembeng 15:6f2798e45099 535 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 536 ERROR("Shadow Connection Error %d", rc);
ampembeng 15:6f2798e45099 537 return rc;
Janos Follath 0:fc70c47eecb4 538 }
Janos Follath 0:fc70c47eecb4 539
ampembeng 15:6f2798e45099 540 // Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
ampembeng 15:6f2798e45099 541 // #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
ampembeng 15:6f2798e45099 542 // #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
ampembeng 15:6f2798e45099 543 rc = mqttClient.setAutoReconnectStatus(true);
ampembeng 15:6f2798e45099 544 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 545 ERROR("Unable to set Auto Reconnect to true - %d", rc);
ampembeng 15:6f2798e45099 546 return rc;
ampembeng 15:6f2798e45099 547 }
ampembeng 15:6f2798e45099 548
ampembeng 15:6f2798e45099 549 // Example line of how to delete a shadow (not used in this demo)
ampembeng 15:6f2798e45099 550 //aws_iot_shadow_delete(&mqttClient, AWS_IOT_MY_THING_NAME, ShadowUpdateStatusCallback, NULL, 8, true);
Janos Follath 0:fc70c47eecb4 551
ampembeng 15:6f2798e45099 552 INFO("Shadow Register Delta...");
ampembeng 15:6f2798e45099 553 rc = aws_iot_shadow_register_delta(&mqttClient, &ledController);
ampembeng 15:6f2798e45099 554 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 555 ERROR("Shadow Register Delta Error");
ampembeng 15:6f2798e45099 556 return rc;
ampembeng 15:6f2798e45099 557 }
ampembeng 15:6f2798e45099 558
ampembeng 15:6f2798e45099 559 INFO("Will attempt to sync with device shadow every %f seconds.", SHADOW_SYNC_INTERVAL);
ampembeng 15:6f2798e45099 560 // Loop and publish changes from the FRDM board
ampembeng 15:6f2798e45099 561 while (NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc) {
ampembeng 15:6f2798e45099 562
ampembeng 15:6f2798e45099 563 // Looks for incoming socket messages
ampembeng 15:6f2798e45099 564 rc = aws_iot_shadow_yield(&mqttClient, 200);
ampembeng 15:6f2798e45099 565 if (NETWORK_ATTEMPTING_RECONNECT == rc) {
ampembeng 15:6f2798e45099 566 // If the client is attempting to reconnect we will skip the rest of the loop.
ampembeng 15:6f2798e45099 567 INFO("Attempting to reconnect...");
ampembeng 15:6f2798e45099 568 wait(1);
ampembeng 15:6f2798e45099 569 continue;
ampembeng 15:6f2798e45099 570 }
ampembeng 20:ee34856ae510 571
ampembeng 20:ee34856ae510 572 // Read sensor data
ampembeng 20:ee34856ae510 573 temperature = CTOF(hts221.readTemperature());
ampembeng 20:ee34856ae510 574 humidity = hts221.readHumidity();
ampembeng 20:ee34856ae510 575
ampembeng 15:6f2798e45099 576 INFO("\n=======================================================================================\n");
ampembeng 15:6f2798e45099 577 // Initialize JSON shadow document
ampembeng 15:6f2798e45099 578 rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
ampembeng 15:6f2798e45099 579 if (rc == NONE_ERROR) {
ampembeng 15:6f2798e45099 580
ampembeng 15:6f2798e45099 581 // If there has been a SW3 button press update the 'desired' color
ampembeng 15:6f2798e45099 582 if (buttonOverride) {
ampembeng 23:b9ff83dc965f 583 rc = aws_iot_shadow_add_desired(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 1, &ledController);
ampembeng 15:6f2798e45099 584 buttonOverride = false;
Janos Follath 0:fc70c47eecb4 585 }
ampembeng 15:6f2798e45099 586
ampembeng 23:b9ff83dc965f 587 // Updates the 'reported' color/temp/humidity
ampembeng 20:ee34856ae510 588 rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3, &ledController,
ampembeng 20:ee34856ae510 589 &temperatureHandler,
ampembeng 20:ee34856ae510 590 &humidityHandler);
ampembeng 15:6f2798e45099 591
ampembeng 15:6f2798e45099 592 if (rc == NONE_ERROR) {
ampembeng 15:6f2798e45099 593 rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
ampembeng 15:6f2798e45099 594
ampembeng 15:6f2798e45099 595 if (rc == NONE_ERROR) {
ampembeng 15:6f2798e45099 596 INFO("Update Shadow: %s", JsonDocumentBuffer);
ampembeng 18:6370da1de572 597 rc = aws_iot_shadow_update(&mqttClient, sp.pMyThingName, JsonDocumentBuffer,
ampembeng 15:6f2798e45099 598 ShadowUpdateStatusCallback, NULL, 8, true);
ampembeng 15:6f2798e45099 599 }
ampembeng 15:6f2798e45099 600 }
ampembeng 20:ee34856ae510 601 }
ampembeng 20:ee34856ae510 602
ampembeng 20:ee34856ae510 603 // Print data
ampembeng 23:b9ff83dc965f 604 printData();
ampembeng 18:6370da1de572 605 INFO("*****************************************************************************************");
ampembeng 20:ee34856ae510 606
ampembeng 20:ee34856ae510 607 // Set the LED color
ampembeng 15:6f2798e45099 608 SetLedColor(ledColor);
ampembeng 15:6f2798e45099 609 wait(SHADOW_SYNC_INTERVAL);
Janos Follath 0:fc70c47eecb4 610 }
Janos Follath 0:fc70c47eecb4 611
ampembeng 15:6f2798e45099 612 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 613 ERROR("An error occurred in the loop %d", rc);
Janos Follath 0:fc70c47eecb4 614 }
Janos Follath 0:fc70c47eecb4 615
ampembeng 15:6f2798e45099 616 INFO("Disconnecting");
ampembeng 15:6f2798e45099 617 rc = aws_iot_shadow_disconnect(&mqttClient);
ampembeng 15:6f2798e45099 618
ampembeng 15:6f2798e45099 619 if (NONE_ERROR != rc) {
ampembeng 15:6f2798e45099 620 ERROR("Disconnect error %d", rc);
Janos Follath 0:fc70c47eecb4 621 }
Janos Follath 0:fc70c47eecb4 622
ampembeng 15:6f2798e45099 623 return rc;
ampembeng 15:6f2798e45099 624 }