Created
June 28, 2019 20:38
-
-
Save chegewara/cff1d7586855d11a6caa198a6d736158 to your computer and use it in GitHub Desktop.
heap test in afr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file iot_demo_afr.c | |
* @brief Generic demo runner for C SDK libraries on Amazon FreeRTOS. | |
*/ | |
/* The config header is always included first. */ | |
#include "iot_config.h" | |
#include <string.h> | |
#include "aws_clientcredential.h" | |
#include "aws_clientcredential_keys.h" | |
#include "iot_demo_logging.h" | |
#include "iot_network_manager_private.h" | |
#include "platform/iot_threads.h" | |
#include "aws_demo.h" | |
#include "iot_init.h" | |
/* Remove dependency to MQTT */ | |
#define MQTT_DEMO_TYPE_ENABLED (defined(CONFIG_MQTT_DEMO_ENABLED)||defined(CONFIG_SHADOW_DEMO_ENABLED)||defined(CONFIG_DEFENDER_DEMO_ENABLED)||defined(CONFIG_OTA_UPDATE_DEMO_ENABLED)) | |
#if MQTT_DEMO_TYPE_ENABLED | |
#include "iot_mqtt.h" | |
#endif | |
static IotNetworkManagerSubscription_t subscription = IOT_NETWORK_MANAGER_SUBSCRIPTION_INITIALIZER; | |
/* Semaphore used to wait for a network to be available. */ | |
static IotSemaphore_t demoNetworkSemaphore; | |
/* Variable used to indicate the connected network. */ | |
static uint32_t demoConnectedNetwork = AWSIOT_NETWORK_TYPE_NONE; | |
#if MQTT_DEMO_TYPE_ENABLED | |
#if BLE_ENABLED | |
extern const IotMqttSerializer_t IotBleMqttSerializer; | |
#endif | |
/*-----------------------------------------------------------*/ | |
const IotMqttSerializer_t * demoGetMqttSerializer( void ) | |
{ | |
const IotMqttSerializer_t * ret = NULL; | |
#if BLE_ENABLED | |
if( demoConnectedNetwork == AWSIOT_NETWORK_TYPE_BLE ) | |
{ | |
ret = &IotBleMqttSerializer; | |
} | |
#endif | |
return ret; | |
} | |
#endif | |
/*-----------------------------------------------------------*/ | |
void generateDeviceIdentifierAndMetrics( void ); | |
static uint32_t _getConnectedNetworkForDemo( demoContext_t * pDemoContext ) | |
{ | |
uint32_t ret = ( AwsIotNetworkManager_GetConnectedNetworks() & pDemoContext->networkTypes ); | |
if( ( ret & AWSIOT_NETWORK_TYPE_WIFI ) == AWSIOT_NETWORK_TYPE_WIFI ) | |
{ | |
ret = AWSIOT_NETWORK_TYPE_WIFI; | |
} | |
else if( ( ret & AWSIOT_NETWORK_TYPE_BLE ) == AWSIOT_NETWORK_TYPE_BLE ) | |
{ | |
ret = AWSIOT_NETWORK_TYPE_BLE; | |
} | |
else if( ( ret & AWSIOT_NETWORK_TYPE_ETH ) == AWSIOT_NETWORK_TYPE_ETH ) | |
{ | |
ret = AWSIOT_NETWORK_TYPE_ETH; | |
} | |
else | |
{ | |
ret = AWSIOT_NETWORK_TYPE_NONE; | |
} | |
return ret; | |
} | |
/*-----------------------------------------------------------*/ | |
static uint32_t _waitForDemoNetworkConnection( demoContext_t * pDemoContext ) | |
{ | |
IotSemaphore_Wait( &demoNetworkSemaphore ); | |
return _getConnectedNetworkForDemo( pDemoContext ); | |
} | |
/*-----------------------------------------------------------*/ | |
static void _onNetworkStateChangeCallback( uint32_t network, | |
AwsIotNetworkState_t state, | |
void * pContext ) | |
{ | |
const IotNetworkInterface_t * pNetworkInterface = NULL; | |
void *pConnectionParams = NULL, *pCredentials = NULL; | |
demoContext_t * pDemoContext = ( demoContext_t * ) pContext; | |
if( ( state == eNetworkStateEnabled ) && ( demoConnectedNetwork == AWSIOT_NETWORK_TYPE_NONE ) ) | |
{ | |
demoConnectedNetwork = network; | |
IotSemaphore_Post( &demoNetworkSemaphore ); | |
if( pDemoContext->networkConnectedCallback != NULL ) | |
{ | |
pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( network ); | |
pConnectionParams = AwsIotNetworkManager_GetConnectionParams( network ); | |
pCredentials = AwsIotNetworkManager_GetCredentials( network ), | |
pDemoContext->networkConnectedCallback( true, | |
clientcredentialIOT_THING_NAME, | |
pConnectionParams, | |
pCredentials, | |
pNetworkInterface ); | |
} | |
} | |
else if( ( state == eNetworkStateDisabled ) && ( demoConnectedNetwork == network ) ) | |
{ | |
if( pDemoContext->networkDisconnectedCallback != NULL ) | |
{ | |
pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( network ); | |
pDemoContext->networkDisconnectedCallback( pNetworkInterface ); | |
} | |
demoConnectedNetwork = _getConnectedNetworkForDemo( pDemoContext ); | |
if( demoConnectedNetwork != AWSIOT_NETWORK_TYPE_NONE ) | |
{ | |
if( pDemoContext->networkConnectedCallback != NULL ) | |
{ | |
pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( demoConnectedNetwork ); | |
pConnectionParams = AwsIotNetworkManager_GetConnectionParams( demoConnectedNetwork ); | |
pCredentials = AwsIotNetworkManager_GetCredentials( demoConnectedNetwork ); | |
pDemoContext->networkConnectedCallback( true, | |
clientcredentialIOT_THING_NAME, | |
pConnectionParams, | |
pCredentials, | |
pNetworkInterface ); | |
} | |
} | |
} | |
} | |
/** | |
* @brief Initialize the common libraries, Mqtt library and network manager. | |
* | |
* @return `EXIT_SUCCESS` if all libraries were successfully initialized; | |
* `EXIT_FAILURE` otherwise. | |
*/ | |
static int _initialize( demoContext_t * pContext ) | |
{ | |
int status = EXIT_SUCCESS; | |
bool commonLibrariesInitailized = false; | |
bool semaphoreCreated = false; | |
/* Generate device identifier and device metrics. */ | |
// generateDeviceIdentifierAndMetrics(); | |
/* Initialize common libraries required by network manager and demo. */ | |
if( IotSdk_Init() == true ) | |
{ | |
commonLibrariesInitailized = true; | |
} | |
else | |
{ | |
IotLogInfo( "Failed to initialize the common library." ); | |
status = EXIT_FAILURE; | |
} | |
if( status == EXIT_SUCCESS ) | |
{ | |
if( AwsIotNetworkManager_Init() != pdTRUE ) | |
{ | |
IotLogError( "Failed to initialize network manager library." ); | |
status = EXIT_FAILURE; | |
} | |
} | |
if( status == EXIT_SUCCESS ) | |
{ | |
/* Create semaphore to signal that a network is available for the demo. */ | |
if( IotSemaphore_Create( &demoNetworkSemaphore, 0, 1 ) != true ) | |
{ | |
IotLogError( "Failed to create semaphore to wait for a network connection." ); | |
status = EXIT_FAILURE; | |
} | |
else | |
{ | |
semaphoreCreated = true; | |
} | |
} | |
if( status == EXIT_SUCCESS ) | |
{ | |
/* Subscribe for network state change from Network Manager. */ | |
if( AwsIotNetworkManager_SubscribeForStateChange( pContext->networkTypes, | |
_onNetworkStateChangeCallback, | |
pContext, | |
&subscription ) != pdTRUE ) | |
{ | |
IotLogError( "Failed to subscribe network state change callback." ); | |
status = EXIT_FAILURE; | |
} | |
} | |
/* Initialize all the networks configured for the device. */ | |
if( status == EXIT_SUCCESS ) | |
{ | |
if( AwsIotNetworkManager_EnableNetwork( configENABLED_NETWORKS ) != configENABLED_NETWORKS ) | |
{ | |
IotLogError( "Failed to intialize all the networks configured for the device." ); | |
status = EXIT_FAILURE; | |
} | |
} | |
if( status == EXIT_SUCCESS ) | |
{ | |
/* Wait for network configured for the demo to be initialized. */ | |
demoConnectedNetwork = _getConnectedNetworkForDemo( pContext ); | |
if( demoConnectedNetwork == AWSIOT_NETWORK_TYPE_NONE ) | |
{ | |
/* Network not yet initialized. Block for a network to be intialized. */ | |
IotLogInfo( "No networks connected for the demo. Waiting for a network connection. " ); | |
demoConnectedNetwork = _waitForDemoNetworkConnection( pContext ); | |
} | |
} | |
if( status == EXIT_FAILURE ) | |
{ | |
if( semaphoreCreated == true ) | |
{ | |
IotSemaphore_Destroy( &demoNetworkSemaphore ); | |
} | |
if( commonLibrariesInitailized == true ) | |
{ | |
IotSdk_Cleanup(); | |
} | |
} | |
return status; | |
} | |
/** | |
* @brief Clean up the common libraries and the MQTT library. | |
*/ | |
static void _cleanup( void ) | |
{ | |
/* Remove network manager subscription */ | |
AwsIotNetworkManager_RemoveSubscription( subscription ); | |
IotSemaphore_Destroy( &demoNetworkSemaphore ); | |
IotSdk_Cleanup(); | |
} | |
/*-----------------------------------------------------------*/ | |
void runDemoTask( void * pArgument ) | |
{ | |
/* On Amazon FreeRTOS, credentials and server info are defined in a header | |
* and set by the initializers. */ | |
demoContext_t * pContext = ( demoContext_t * ) pArgument; | |
const IotNetworkInterface_t * pNetworkInterface = NULL; | |
void *pConnectionParams = NULL, *pCredentials = NULL; | |
int status; | |
status = _initialize( pContext ); | |
if( status == EXIT_SUCCESS ) | |
{ | |
IotLogInfo( "Successfully initialized the demo. Network type for the demo: %d", demoConnectedNetwork ); | |
} | |
else | |
{ | |
IotLogError( "Failed to initialize the demo. exiting..." ); | |
} | |
vTaskDelete( NULL ); | |
} | |
/*-----------------------------------------------------------*/ | |
#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) | |
BaseType_t xApplicationDNSQueryHook( const char * pcName ) | |
{ | |
BaseType_t xReturn; | |
/* Determine if a name lookup is for this node. Two names are given | |
* to this node: that returned by pcApplicationHostnameHook() and that set | |
* by mainDEVICE_NICK_NAME. */ | |
if( strcmp( pcName, pcApplicationHostnameHook() ) == 0 ) | |
{ | |
xReturn = pdPASS; | |
} | |
else if( strcmp( pcName, mainDEVICE_NICK_NAME ) == 0 ) | |
{ | |
xReturn = pdPASS; | |
} | |
else | |
{ | |
xReturn = pdFAIL; | |
} | |
return xReturn; | |
} | |
#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */ | |
/*-----------------------------------------------------------*/ | |
/** | |
* @brief Warn user if pvPortMalloc fails. | |
* | |
* Called if a call to pvPortMalloc() fails because there is insufficient | |
* free memory available in the FreeRTOS heap. pvPortMalloc() is called | |
* internally by FreeRTOS API functions that create tasks, queues, software | |
* timers, and semaphores. The size of the FreeRTOS heap is set by the | |
* configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. | |
* | |
*/ | |
void vApplicationMallocFailedHook() | |
{ | |
configPRINTF( ( "ERROR: Malloc failed to allocate memory\r\n" ) ); | |
taskDISABLE_INTERRUPTS(); | |
/* Loop forever */ | |
for( ; ; ) | |
{ | |
} | |
} | |
/*-----------------------------------------------------------*/ | |
/** | |
* @brief Loop forever if stack overflow is detected. | |
* | |
* If configCHECK_FOR_STACK_OVERFLOW is set to 1, | |
* this hook provides a location for applications to | |
* define a response to a stack overflow. | |
* | |
* Use this hook to help identify that a stack overflow | |
* has occurred. | |
* | |
*/ | |
void vApplicationStackOverflowHook( TaskHandle_t xTask, | |
char * pcTaskName ) | |
{ | |
configPRINTF( ( "ERROR: stack overflow with task %s\r\n", pcTaskName ) ); | |
portDISABLE_INTERRUPTS(); | |
/* Unused Parameters */ | |
( void ) xTask; | |
/* Loop forever */ | |
for( ; ; ) | |
{ | |
} | |
} | |
/* | |
* @brief Total length of the hash in bytes. | |
*/ | |
#define _MD5_HASH_LENGTH_BYTES ( 16 ) | |
/* | |
* @brief Length in 32-bit words of each chunk used for hash computation . | |
*/ | |
#define _MD5_CHUNK_LENGTH_WORDS ( 16 ) | |
/* | |
* Encode Length of one byte. | |
*/ | |
#define _BYTE_ENCODE_LENGTH ( 2 ) | |
/* | |
* @brief Length in bytes of each chunk used for hash computation. | |
*/ | |
#define _MD5_CHUNK_LENGTH_BYTES ( _MD5_CHUNK_LENGTH_WORDS * 4 ) | |
#define LEFT_ROTATE( x, c ) ( ( x << c ) | ( x >> ( 32 - c ) ) ) | |
static const char S[64] = { | |
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, | |
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, | |
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, | |
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 | |
}; | |
static const unsigned int K[64] = { | |
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | |
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | |
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | |
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, | |
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | |
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | |
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | |
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, | |
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | |
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, | |
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, | |
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, | |
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, | |
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, | |
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 | |
}; | |
/* | |
* @brief MD5 hashing algorithm to generate unique identifier for a sequeunce of bytes. | |
* The hash algorithm is adapted from wikipedia and does not dependent on any third party libraries. | |
*/ | |
static void _generateHash( const char *pData, size_t dataLength, uint8_t *pHash, size_t hashLength ) | |
{ | |
uint32_t A, B, C, D, F, G; | |
uint32_t chunk[ _MD5_CHUNK_LENGTH_WORDS ] = { 0 }; | |
const uint32_t *pCurrent = NULL; | |
uint32_t *pOutput = ( uint32_t * )pHash; | |
size_t i; | |
//Initialize variables | |
pOutput[ 0 ] = 0x67452301; | |
pOutput[ 1 ] = 0xefcdab89; | |
pOutput[ 2 ] = 0x98badcfe; | |
pOutput[ 3 ] = 0x10325476; | |
configASSERT( hashLength >= _MD5_HASH_LENGTH_BYTES ); | |
while( dataLength > 0 ) | |
{ | |
A = pOutput[ 0 ]; | |
B = pOutput[ 1 ]; | |
C = pOutput[ 2 ]; | |
D = pOutput[ 3 ]; | |
F = G = 0; | |
if( dataLength < _MD5_CHUNK_LENGTH_BYTES ) | |
{ | |
memcpy( chunk, pData, dataLength ); | |
pCurrent = chunk; | |
pData += _MD5_CHUNK_LENGTH_BYTES; | |
dataLength = 0; | |
} | |
else | |
{ | |
pCurrent = ( uint32_t * ) pData; | |
pData += _MD5_CHUNK_LENGTH_BYTES; | |
dataLength -= _MD5_CHUNK_LENGTH_BYTES; | |
} | |
for( i = 0; i < 64; i++ ) | |
{ | |
if( i < 16 ) | |
{ | |
F = ( B & C ) | ( ( ~B ) & D ); | |
G = i; | |
} | |
else if( i < 32 ) | |
{ | |
F = ( D & B ) | ( ( ~D ) & C ); | |
G = ( ( 5 * i ) + 1 ) % 16; | |
} | |
else if( i < 48 ) | |
{ | |
F = ( B ^ C ) ^ D; | |
G = ( ( 3 * i ) + 5 ) % 16; | |
} | |
else | |
{ | |
F = C ^ ( B | ( ~D ) ); | |
G = ( 7 * i ) % 16; | |
} | |
F = F + A + K[ i ] + pCurrent[ G ]; | |
A = D; | |
D = C; | |
C = B; | |
B = B + LEFT_ROTATE( F, S[ i ] ); | |
} | |
pOutput[ 0 ] += A; | |
pOutput[ 1 ] += B; | |
pOutput[ 2 ] += C; | |
pOutput[ 3 ] += D; | |
} | |
} | |
/* | |
* @brief Length of device identifier. | |
* Device identifier is represented as hex string of MD5 hash of the device certificate. | |
*/ | |
#define AWS_IOT_DEVICE_IDENTIFIER_LENGTH ( _MD5_HASH_LENGTH_BYTES * 2 ) | |
/** | |
* @brief Device metrics name format | |
*/ | |
#define AWS_IOT_METRICS_NAME "?SDK=" IOT_SDK_NAME "&Version=4.0.0&Platform=" IOT_PLATFORM_NAME "&AFRDevID=%.*s" | |
/** | |
* @brief Length of #AWS_IOT_METRICS_NAME. | |
*/ | |
#define AWS_IOT_METRICS_NAME_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_NAME ) + AWS_IOT_DEVICE_IDENTIFIER_LENGTH ) ) | |
/** | |
* @brief Unique identifier for the device. | |
*/ | |
static char deviceIdentifier[ AWS_IOT_DEVICE_IDENTIFIER_LENGTH + 1] = { 0 }; | |
/* | |
@brief Device metrics sent to the cloud. | |
*/ | |
static char deviceMetrics[AWS_IOT_METRICS_NAME_LENGTH + 1] = { 0 }; | |
static void _generateDeviceMetrics(void) | |
{ | |
size_t length; | |
length = snprintf( deviceMetrics, | |
AWS_IOT_METRICS_NAME_LENGTH, | |
AWS_IOT_METRICS_NAME, | |
AWS_IOT_DEVICE_IDENTIFIER_LENGTH, | |
deviceIdentifier ); | |
configASSERT(length > 0); | |
} | |
/* | |
* @brief Generates a unique identifier for the device and metrics sent by the device to cloud. | |
* Function should only be called once at intialization. | |
*/ | |
void generateDeviceIdentifierAndMetrics( void ) | |
{ | |
const char *pCert = keyCLIENT_CERTIFICATE_PEM; | |
size_t certLength = strlen( keyCLIENT_CERTIFICATE_PEM ); | |
uint8_t hash[ _MD5_HASH_LENGTH_BYTES ] = { 0 }; | |
char *pBuffer = deviceIdentifier; | |
int i; | |
size_t ret; | |
if ( ( NULL == pCert ) || ( 0 == strcmp("", pCert ) ) ) | |
{ | |
configPRINTF(( "ERROR: Generating device identifier and metrics requires a valid certificate.\r\n" )); | |
/* Duplicating the check in assert to force compiler to not optimize it. */ | |
configASSERT( ( NULL != pCert ) && ( 0 != strcmp( "", pCert ) ) ); | |
} | |
else | |
{ | |
_generateHash(pCert, certLength, hash, _MD5_HASH_LENGTH_BYTES); | |
for( i = 0; i < _MD5_HASH_LENGTH_BYTES; i++ ) | |
{ | |
ret = snprintf( pBuffer, ( _BYTE_ENCODE_LENGTH + 1 ), "%02X", hash[ i ] ); | |
configASSERT( ret > 0 ); | |
pBuffer += _BYTE_ENCODE_LENGTH; | |
} | |
_generateDeviceMetrics(); | |
} | |
} | |
/* | |
* @brief Retrieves the unique identifier for the device. | |
*/ | |
const char *getDeviceIdentifier( void ) | |
{ | |
return deviceIdentifier; | |
} | |
/* | |
* @brief Retrieves the device metrics to be sent to cloud. | |
*/ | |
const char *getDeviceMetrics( void ) | |
{ | |
return deviceMetrics; | |
} | |
/* | |
* @brief Get the device metrics length. | |
*/ | |
uint16_t getDeviceMetricsLength( void ) | |
{ | |
return ( uint16_t )( strlen( deviceMetrics ) ); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Amazon FreeRTOS V1.4.7 | |
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |
* this software and associated documentation files (the "Software"), to deal in | |
* the Software without restriction, including without limitation the rights to | |
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
* the Software, and to permit persons to whom the Software is furnished to do so, | |
* subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | |
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
* | |
* http://aws.amazon.com/freertos | |
* http://www.FreeRTOS.org | |
*/ | |
#include "iot_config.h" | |
/* FreeRTOS includes. */ | |
#include "FreeRTOS.h" | |
#include "task.h" | |
/* Demo includes */ | |
#include "aws_demo.h" | |
#include "aws_dev_mode_key_provisioning.h" | |
/* AWS System includes. */ | |
#include "bt_hal_manager.h" | |
#include "aws_system_init.h" | |
#include "aws_logging_task.h" | |
#include "nvs_flash.h" | |
#include "FreeRTOS_Sockets.h" | |
#include "esp_system.h" | |
#include "esp_wifi.h" | |
#include "esp_interface.h" | |
#include "esp_gap_ble_api.h" | |
#include "esp_bt.h" | |
#include "esp_bt_main.h" | |
#include "esp_log.h" | |
#include "iot_mqtt.h" | |
#include "aws_iot_shadow.h" | |
#include "driver/uart.h" | |
#include "aws_application_version.h" | |
#include "iot_demo_logging.h" | |
#include "aws_ota_agent.h" | |
#include "platform/iot_clock.h" | |
#include "iot_network_manager_private.h" | |
#if BLE_ENABLED | |
#include "bt_hal_manager_adapter_ble.h" | |
#include "bt_hal_manager.h" | |
#include "bt_hal_gatt_server.h" | |
#include "iot_ble.h" | |
#include "iot_ble_config.h" | |
#include "iot_ble_wifi_provisioning.h" | |
#include "iot_ble_numericComparison.h" | |
#endif | |
#include "esp_log.h" | |
#define TAG __func__ | |
/* Logging Task Defines. */ | |
#define mainLOGGING_MESSAGE_QUEUE_LENGTH ( 32 ) | |
#define mainLOGGING_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) | |
#define mainDEVICE_NICK_NAME "Espressif_Demo" | |
#define KEEP_ALIVE_SECONDS ( 60 ) | |
#define TIMEOUT_MS ( 5000 ) | |
QueueHandle_t spp_uart_queue = NULL; | |
esp_err_t get_thing_name(); | |
static void connectTask(void* p); | |
IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; | |
IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; | |
static IotMqttConnection_t mqttConnection; | |
/* Static arrays for FreeRTOS+TCP stack initialization for Ethernet network connections | |
* are use are below. If you are using an Ethernet connection on your MCU device it is | |
* recommended to use the FreeRTOS+TCP stack. The default values are defined in | |
* FreeRTOSConfig.h. */ | |
/** | |
* @brief Initializes the board. | |
*/ | |
static void prvMiscInitialization( void ); | |
#if BLE_ENABLED | |
/* Initializes bluetooth */ | |
static esp_err_t prvBLEStackInit( void ); | |
static void spp_uart_init(void); | |
#endif | |
/*-----------------------------------------------------------*/ | |
void tasksStatus(); | |
/** | |
* @brief Application runtime entry point. | |
*/ | |
int app_main( void ) | |
{ | |
/* Perform any hardware initialization that does not require the RTOS to be | |
* running. */ | |
prvMiscInitialization(); | |
if( SYSTEM_Init() == pdPASS ) | |
{ | |
/* A simple example to demonstrate key and certificate provisioning in | |
* microcontroller flash using PKCS#11 interface. This should be replaced | |
* by production ready key provisioning mechanism. */ | |
// vDevModeKeyProvisioning(); | |
#if BLE_ENABLED | |
/* Initialize BLE. */ | |
if( prvBLEStackInit() != ESP_OK ) | |
{ | |
configPRINTF(("Failed to initialize the bluetooth stack\n ")); | |
while( 1 ) | |
{ | |
} | |
} | |
#else | |
ESP_ERROR_CHECK( esp_bt_controller_mem_release( ESP_BT_MODE_CLASSIC_BT ) ); | |
ESP_ERROR_CHECK( esp_bt_controller_mem_release( ESP_BT_MODE_BLE ) ); | |
#endif | |
DEMO_RUNNER_RunDemos(); | |
heap_caps_print_heap_info(MALLOC_CAP_DEFAULT); | |
esp_bluedroid_disable(); | |
esp_bluedroid_deinit(); | |
esp_bt_controller_disable(); | |
esp_bt_controller_deinit(); | |
ESP_ERROR_CHECK( esp_bt_controller_mem_release( ESP_BT_MODE_BLE ) ); | |
heap_caps_print_heap_info(MALLOC_CAP_DEFAULT); | |
xTaskCreate(connectTask, "conT", 4*1024, NULL, 5, NULL); | |
// client code here | |
} | |
tasksStatus(); | |
return 0; | |
} | |
/*-----------------------------------------------------------*/ | |
extern void vApplicationIPInit( void ); | |
static void prvMiscInitialization( void ) | |
{ | |
// Initialize NVS | |
esp_err_t ret = nvs_flash_init(); | |
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { | |
ESP_ERROR_CHECK(nvs_flash_erase()); | |
ret = nvs_flash_init(); | |
} | |
ESP_ERROR_CHECK( ret ); | |
#if BLE_ENABLED | |
NumericComparisonInit(); | |
spp_uart_init(); | |
#endif | |
/* Create tasks that are not dependent on the WiFi being initialized. */ | |
xLoggingTaskInitialize( mainLOGGING_TASK_STACK_SIZE, | |
tskIDLE_PRIORITY+5, | |
mainLOGGING_MESSAGE_QUEUE_LENGTH ); | |
vApplicationIPInit(); | |
if(get_thing_name() == ESP_OK) | |
{ | |
ESP_LOGI(__func__, "thing name: %s", clientcredentialIOT_THING_NAME); | |
} | |
else | |
{ | |
ESP_LOGE(TAG, "can't get thing name"); | |
} | |
if(get_settings() != ESP_OK) | |
{ | |
ESP_LOGE(TAG, "cant read settings from NVS"); | |
settings.clock.display = true; | |
settings.clock.timezone = 0; | |
settings.clock.format = true; | |
settings.display.brightness = 50; | |
settings.display.timeout = 0; | |
settings.wifi.autoconnect = false; | |
} | |
else{ | |
ESP_LOG_BUFFER_HEX("read settings", &settings, sizeof(system_settings_t)); | |
autoConnect = settings.wifi.autoconnect; | |
// autoConnect = true; | |
ESP_LOGI(TAG, "read settings from NVS, %d", autoConnect); | |
} | |
} | |
/*-----------------------------------------------------------*/ | |
#if BLE_ENABLED | |
static esp_err_t prvBLEStackInit( void ) | |
{ | |
/* Initialize BLE */ | |
esp_err_t xRet = ESP_OK; | |
esp_bt_controller_config_t xBtCfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); | |
ESP_ERROR_CHECK( esp_bt_controller_mem_release( ESP_BT_MODE_CLASSIC_BT ) ); | |
xRet = esp_bt_controller_init( &xBtCfg ); | |
if( xRet == ESP_OK ) | |
{ | |
xRet = esp_bt_controller_enable( ESP_BT_MODE_BLE ); | |
} | |
else | |
{ | |
configPRINTF( ( "Failed to initialize bt controller, err = %d", xRet ) ); | |
} | |
if( xRet == ESP_OK ) | |
{ | |
xRet = esp_bluedroid_init(); | |
} | |
else | |
{ | |
configPRINTF( ( "Failed to initialize bluedroid stack, err = %d", xRet ) ); | |
} | |
if( xRet == ESP_OK ) | |
{ | |
xRet = esp_bluedroid_enable(); | |
} | |
return xRet; | |
} | |
#endif | |
/*-----------------------------------------------------------*/ | |
#if BLE_ENABLED | |
static void spp_uart_init(void) | |
{ | |
uart_config_t uart_config = { | |
.baud_rate = 115200, | |
.data_bits = UART_DATA_8_BITS, | |
.parity = UART_PARITY_DISABLE, | |
.stop_bits = UART_STOP_BITS_1, | |
.flow_ctrl = UART_HW_FLOWCTRL_RTS, | |
.rx_flow_ctrl_thresh = 122, | |
}; | |
/* Set UART parameters */ | |
uart_param_config(UART_NUM_0, &uart_config); | |
//Set UART pins | |
uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); | |
//Install UART driver, and get the queue. | |
uart_driver_install(UART_NUM_0, 4096, 8192, 10,&spp_uart_queue,0); | |
} | |
/*-----------------------------------------------------------*/ | |
BaseType_t getUserMessage( INPUTMessage_t * pxINPUTmessage, TickType_t xAuthTimeout ) | |
{ | |
uart_event_t xEvent; | |
BaseType_t xReturnMessage = pdFALSE; | |
if (xQueueReceive(spp_uart_queue, (void * )&xEvent, (portTickType) xAuthTimeout )) { | |
switch (xEvent.type) { | |
//Event of UART receiving data | |
case UART_DATA: | |
if (xEvent.size) { | |
pxINPUTmessage->pcData = (uint8_t *)malloc(sizeof(uint8_t)*xEvent.size); | |
if(pxINPUTmessage->pcData != NULL){ | |
memset(pxINPUTmessage->pcData,0x0,xEvent.size); | |
uart_read_bytes(UART_NUM_0, (uint8_t *)pxINPUTmessage->pcData,xEvent.size,portMAX_DELAY); | |
xReturnMessage = pdTRUE; | |
}else | |
{ | |
configPRINTF(("Malloc failed in main.c\n")); | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
return xReturnMessage; | |
} | |
#endif | |
/*-----------------------------------------------------------*/ | |
extern void esp_vApplicationTickHook(); | |
void IRAM_ATTR vApplicationTickHook() | |
{ | |
esp_vApplicationTickHook(); | |
} | |
/*-----------------------------------------------------------*/ | |
extern void esp_vApplicationIdleHook(); | |
void vApplicationIdleHook() | |
{ | |
esp_vApplicationIdleHook(); | |
} | |
/*-----------------------------------------------------------*/ | |
void vApplicationDaemonTaskStartupHook( void ) | |
{ | |
} | |
/*-----------------------------------------------------------*/ | |
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) | |
{ | |
uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress; | |
system_event_t evt; | |
if (eNetworkEvent == eNetworkUp) { | |
/* Print out the network configuration, which may have come from a DHCP | |
* server. */ | |
FreeRTOS_GetAddressConfiguration( | |
&ulIPAddress, | |
&ulNetMask, | |
&ulGatewayAddress, | |
&ulDNSServerAddress ); | |
evt.event_id = SYSTEM_EVENT_STA_GOT_IP; | |
evt.event_info.got_ip.ip_changed = true; | |
evt.event_info.got_ip.ip_info.ip.addr = ulIPAddress; | |
evt.event_info.got_ip.ip_info.netmask.addr = ulNetMask; | |
evt.event_info.got_ip.ip_info.gw.addr = ulGatewayAddress; | |
esp_event_send(&evt); | |
} | |
} | |
static int _establishMqttConnection( const char * pIdentifier, | |
void * pNetworkServerInfo, | |
void * pNetworkCredentialInfo, | |
const IotNetworkInterface_t * pNetworkInterface, | |
IotMqttConnection_t * pMqttConnection ) | |
{ | |
int status = EXIT_SUCCESS; | |
IotMqttError_t connectStatus = IOT_MQTT_STATUS_PENDING; | |
if( pIdentifier == NULL ) | |
{ | |
IotLogError( "Shadow Thing Name must be provided." ); | |
status = EXIT_FAILURE; | |
} | |
if( status == EXIT_SUCCESS ) | |
{ | |
/* Set the members of the network info not set by the initializer. This | |
* struct provided information on the transport layer to the MQTT connection. */ | |
networkInfo.createNetworkConnection = true; | |
networkInfo.u.setup.pNetworkServerInfo = pNetworkServerInfo; | |
networkInfo.u.setup.pNetworkCredentialInfo = pNetworkCredentialInfo; | |
networkInfo.pNetworkInterface = pNetworkInterface; | |
#if ( IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 ) && defined( IOT_DEMO_MQTT_SERIALIZER ) | |
networkInfo.pMqttSerializer = IOT_DEMO_MQTT_SERIALIZER; | |
#endif | |
/* Set the members of the connection info not set by the initializer. */ | |
connectInfo.awsIotMqttMode = true; | |
connectInfo.cleanSession = true; | |
connectInfo.keepAliveSeconds = KEEP_ALIVE_SECONDS; | |
/* AWS IoT recommends the use of the Thing Name as the MQTT client ID. */ | |
connectInfo.pClientIdentifier = pIdentifier; | |
connectInfo.clientIdentifierLength = ( uint16_t ) strlen( pIdentifier ); | |
IotLogInfo( "Shadow Thing Name is %.*s (length %hu).", | |
connectInfo.clientIdentifierLength, | |
connectInfo.pClientIdentifier, | |
connectInfo.clientIdentifierLength ); | |
/* Establish the MQTT connection. */ | |
do{ | |
connectStatus = IotMqtt_Connect( &networkInfo, | |
&connectInfo, | |
TIMEOUT_MS, | |
pMqttConnection ); | |
if( connectStatus != IOT_MQTT_SUCCESS ) | |
{ | |
IotLogError( "MQTT CONNECT returned error %s.", | |
IotMqtt_strerror( connectStatus ) ); | |
IotClock_SleepMs(1000); | |
} | |
} while ( connectStatus != IOT_MQTT_SUCCESS ); | |
} | |
return status; | |
} | |
static int _initializeMqtt( void ) | |
{ | |
int status = EXIT_SUCCESS; | |
IotMqttError_t mqttInitStatus = IOT_MQTT_SUCCESS; | |
AwsIotShadowError_t shadowInitStatus = AWS_IOT_SHADOW_SUCCESS; | |
/* Flags to track cleanup on error. */ | |
bool mqttInitialized = false; | |
/* Initialize the MQTT library. */ | |
mqttInitStatus = IotMqtt_Init(); | |
if( mqttInitStatus == IOT_MQTT_SUCCESS ) | |
{ | |
mqttInitialized = true; | |
} | |
else | |
{ | |
status = EXIT_FAILURE; | |
} | |
return status; | |
} | |
static void connectTask(void* p); | |
static void _disconnectCallback( void * pCallbackContext, IotMqttCallbackParam_t * pCallbackParam ) | |
{ | |
ESP_LOGE(__func__, "mqtt disconnect callback"); | |
int status = 0; | |
/** | |
* Deinit shadow and OTA task on disconnect from mqtt, so we could make clean start when wifi connection is restored | |
*/ | |
AwsIotShadow_Cleanup(); | |
do | |
{ | |
ESP_LOGE(__func__, "OTA shutdown"); | |
status = OTA_AgentShutdown(500); | |
ESP_LOGE(__func__, "OTA shutdown => %d", status); | |
} while(status != eOTA_AgentState_NotReady); | |
xTaskCreate(connectTask, "connectT", 4*1024, NULL, 5, NULL); | |
} | |
static void connectTask(void* p) | |
{ | |
uint32_t demoConnectedNetwork = AWSIOT_NETWORK_TYPE_WIFI; | |
const IotNetworkInterface_t * pNetworkInterface = NULL; | |
void *pConnectionParams = NULL, *pCredentials = NULL; | |
mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER; | |
pNetworkInterface = AwsIotNetworkManager_GetNetworkInterface( demoConnectedNetwork ); | |
pConnectionParams = AwsIotNetworkManager_GetConnectionParams( demoConnectedNetwork ); | |
pCredentials = AwsIotNetworkManager_GetCredentials( demoConnectedNetwork ); | |
int status = EXIT_SUCCESS; | |
networkInfo.disconnectCallback.function = _disconnectCallback; | |
status = _establishMqttConnection( clientcredentialIOT_THING_NAME, pConnectionParams, pCredentials, pNetworkInterface, &mqttConnection ); | |
if(status == EXIT_SUCCESS) | |
status = _initializeMqtt(); | |
{ | |
ESP_LOGE(__func__, "Failed to establish connection"); | |
} | |
if(status == EXIT_FAILURE) | |
{ | |
ESP_LOGE(__func__, "Failed to init MQTT"); | |
} | |
vTaskDelete(NULL); | |
} | |
esp_err_t get_thing_name() | |
{ | |
uint32_t ulSize = 0; | |
char *pucBuffer = NULL; | |
nvs_handle xNvsHandle = NULL; | |
esp_err_t xRet = nvs_flash_init_partition("storage"); | |
if(xRet != ESP_OK) | |
ESP_LOGE(TAG, "error 0"); | |
xRet = nvs_open_from_partition("storage", "info", NVS_READONLY, &xNvsHandle); | |
if(xRet != ESP_OK) | |
ESP_LOGE(TAG, "error 1"); | |
xRet = nvs_get_str( xNvsHandle, "thing_name", NULL, &ulSize ); | |
if(xRet != ESP_OK) | |
ESP_LOGE(TAG, "error 2"); | |
if( xRet == ESP_OK ) | |
{ | |
pucBuffer = calloc( 1, ulSize ); | |
if( pucBuffer != NULL ) | |
{ | |
xRet = nvs_get_str( xNvsHandle, "thing_name", pucBuffer, &ulSize ); | |
} | |
else | |
{ | |
xRet = ESP_FAIL; | |
} | |
} | |
if(xRet != ESP_OK) | |
ESP_LOGE(TAG, "error 3"); | |
if( xRet == ESP_OK ) | |
{ | |
strcpy(clientcredentialIOT_THING_NAME, pucBuffer); | |
free(pucBuffer); | |
} | |
nvs_close(xNvsHandle); | |
return xRet; | |
} | |
static void _tasksStatus(void* p) | |
{ | |
UBaseType_t uxArraySize = uxTaskGetNumberOfTasks(); | |
TaskStatus_t pxTaskStatusArray[uxArraySize]; | |
uint32_t pulTotalRunTime = 0; | |
uxTaskGetSystemState(&pxTaskStatusArray[0], uxArraySize, &pulTotalRunTime); | |
for(int i=0; i<uxArraySize; i++) | |
{ | |
ESP_LOGI(__func__, "[%d]Task %s => stack remaining: %d", i, pxTaskStatusArray[i].pcTaskName, pxTaskStatusArray[i].usStackHighWaterMark); | |
} | |
heap_caps_print_heap_info(MALLOC_CAP_DEFAULT); | |
ESP_LOGI(__func__, "stack remaining: %d", uxTaskGetStackHighWaterMark( NULL )); | |
vTaskDelete(NULL); | |
} | |
void tasksStatus() | |
{ | |
xTaskCreate(_tasksStatus, "stackInfo", 5*612, NULL, 1, NULL); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment