Skip to content

Instantly share code, notes, and snippets.

@chegewara
Created June 28, 2019 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chegewara/cff1d7586855d11a6caa198a6d736158 to your computer and use it in GitHub Desktop.
Save chegewara/cff1d7586855d11a6caa198a6d736158 to your computer and use it in GitHub Desktop.
heap test in afr
/**
* @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 ) );
}
/*
* 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