From 040a10b05ce028dcb655dda339ef6c3ac8b97d3e Mon Sep 17 00:00:00 2001 From: Shubham Divekar Date: Mon, 19 Oct 2020 19:03:15 +0000 Subject: [PATCH 1/2] OTA demo directory change --- .../CMakeLists.txt | 4 +- .../aws_iot_ota_update_demo.c | 30 +- .../aws_ota_agent_config.h | 0 .../aws_ota_codesigner_certificate.h | 0 demos/ota/{ => ota_demo_http}/demo_config.h | 8 +- demos/ota/ota_demo_mqtt/CMakeLists.txt | 62 ++ .../ota_demo_mqtt/aws_iot_ota_update_demo.c | 894 ++++++++++++++++++ .../ota/ota_demo_mqtt/aws_ota_agent_config.h | 175 ++++ .../aws_ota_codesigner_certificate.h | 39 + demos/ota/ota_demo_mqtt/demo_config.h | 128 +++ 10 files changed, 1319 insertions(+), 21 deletions(-) rename demos/ota/{ota_demo => ota_demo_http}/CMakeLists.txt (95%) rename demos/ota/{ota_demo => ota_demo_http}/aws_iot_ota_update_demo.c (98%) rename demos/ota/{ => ota_demo_http}/aws_ota_agent_config.h (100%) rename demos/ota/{ => ota_demo_http}/aws_ota_codesigner_certificate.h (100%) rename demos/ota/{ => ota_demo_http}/demo_config.h (95%) create mode 100644 demos/ota/ota_demo_mqtt/CMakeLists.txt create mode 100644 demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c create mode 100644 demos/ota/ota_demo_mqtt/aws_ota_agent_config.h create mode 100644 demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h create mode 100644 demos/ota/ota_demo_mqtt/demo_config.h diff --git a/demos/ota/ota_demo/CMakeLists.txt b/demos/ota/ota_demo_http/CMakeLists.txt similarity index 95% rename from demos/ota/ota_demo/CMakeLists.txt rename to demos/ota/ota_demo_http/CMakeLists.txt index b433624f87..49b4be9f9e 100644 --- a/demos/ota/ota_demo/CMakeLists.txt +++ b/demos/ota/ota_demo_http/CMakeLists.txt @@ -1,4 +1,4 @@ -set( DEMO_NAME "ota_demo" ) +set( DEMO_NAME "ota_demo_http" ) # Include required library's source and header path variables. include( ${CMAKE_SOURCE_DIR}/libraries/aws/ota/otaFilePaths.cmake ) @@ -34,7 +34,7 @@ target_link_libraries( target_include_directories( ${DEMO_NAME} PUBLIC - "${CMAKE_CURRENT_LIST_DIR}/.." + "${CMAKE_CURRENT_LIST_DIR}" "${LOGGING_INCLUDE_DIRS}" ${OTA_INCLUDE_PUBLIC_DIRS} ${OTA_INCLUDE_PRIVATE_DIRS} diff --git a/demos/ota/ota_demo/aws_iot_ota_update_demo.c b/demos/ota/ota_demo_http/aws_iot_ota_update_demo.c similarity index 98% rename from demos/ota/ota_demo/aws_iot_ota_update_demo.c rename to demos/ota/ota_demo_http/aws_iot_ota_update_demo.c index 75f21f32ec..47db704ede 100644 --- a/demos/ota/ota_demo/aws_iot_ota_update_demo.c +++ b/demos/ota/ota_demo_http/aws_iot_ota_update_demo.c @@ -803,20 +803,22 @@ void startOTADemo( MQTTContext_t * pMqttContext ) OTA_GetPacketsProcessed(), OTA_GetPacketsDropped() ) ); - if(state == OtaAgentStateWaitingForJob ) - { - mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "MQTT_ProcessLoop returned with status = %u.", - mqttStatus ) ); - } - } - else - { - sleep( OTA_DEMO_TASK_DELAY_SECONDS ); - } + sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + + // if(state == OtaAgentStateWaitingForJob ) + // { + // mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); + + // if( mqttStatus != MQTTSuccess ) + // { + // LogError( ( "MQTT_ProcessLoop returned with status = %u.", + // mqttStatus ) ); + // } + // } + // else + // { + // sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + // } } diff --git a/demos/ota/aws_ota_agent_config.h b/demos/ota/ota_demo_http/aws_ota_agent_config.h similarity index 100% rename from demos/ota/aws_ota_agent_config.h rename to demos/ota/ota_demo_http/aws_ota_agent_config.h diff --git a/demos/ota/aws_ota_codesigner_certificate.h b/demos/ota/ota_demo_http/aws_ota_codesigner_certificate.h similarity index 100% rename from demos/ota/aws_ota_codesigner_certificate.h rename to demos/ota/ota_demo_http/aws_ota_codesigner_certificate.h diff --git a/demos/ota/demo_config.h b/demos/ota/ota_demo_http/demo_config.h similarity index 95% rename from demos/ota/demo_config.h rename to demos/ota/ota_demo_http/demo_config.h index 560ed425ac..5dd7926f58 100644 --- a/demos/ota/demo_config.h +++ b/demos/ota/ota_demo_http/demo_config.h @@ -40,7 +40,7 @@ #define LIBRARY_LOG_NAME "DEMO" #endif #ifndef LIBRARY_LOG_LEVEL - #define LIBRARY_LOG_LEVEL LOG_INFO + #define LIBRARY_LOG_LEVEL LOG_DEBUG #endif #include "logging_stack.h" @@ -55,7 +55,7 @@ * * #define AWS_IOT_ENDPOINT "...insert here..." */ -#define AWS_IOT_ENDPOINT "a7107zoe0sreq-ats.iot.us-west-2.amazonaws.com" +#define AWS_IOT_ENDPOINT "" /** * @brief AWS IoT MQTT broker port number. @@ -83,7 +83,7 @@ * ROOT_CA_CERT_PATH to the absolute path if this demo is executed from elsewhere. */ #ifndef ROOT_CA_CERT_PATH - #define ROOT_CA_CERT_PATH "certificates/AmazonRootCA1.crt" + #define ROOT_CA_CERT_PATH "/home/ubuntu/dev/aws-iot-device-sdk-embedded-C-staging/demos/certificates/AmazonRootCA1.crt" #endif /** @@ -97,7 +97,6 @@ * * #define CLIENT_CERT_PATH "...insert here..." */ - /** * @brief Path of the file containing the client's private key. * @@ -109,7 +108,6 @@ * * #define CLIENT_PRIVATE_KEY_PATH "...insert here..." */ - /** * @brief MQTT client identifier. * diff --git a/demos/ota/ota_demo_mqtt/CMakeLists.txt b/demos/ota/ota_demo_mqtt/CMakeLists.txt new file mode 100644 index 0000000000..404e411d9c --- /dev/null +++ b/demos/ota/ota_demo_mqtt/CMakeLists.txt @@ -0,0 +1,62 @@ +set( DEMO_NAME "ota_demo_mqtt" ) + +# Include required library's source and header path variables. +include( ${CMAKE_SOURCE_DIR}/libraries/aws/ota/otaFilePaths.cmake ) +include( ${CMAKE_SOURCE_DIR}/libraries/standard/coreMQTT/mqttFilePaths.cmake ) + +# Demo target. +add_executable(${DEMO_NAME}) + +# librt is required to use OTA OS POSIX port. +find_library(LIB_RT rt REQUIRED) + +target_sources( + ${DEMO_NAME} + PRIVATE + "aws_iot_ota_update_demo.c" + ${OTA_SOURCES} + ${OTA_OS_POSIX_SOURCES} + ${OTA_MQTT_SOURCES} + ${MQTT_SOURCES} + ${MQTT_SERIALIZER_SOURCES} +) +target_link_libraries( + ${DEMO_NAME} + PRIVATE + ${LIB_RT} + ota_pal + clock_posix + openssl_posix + retry_utils_posix + mqtt_subscription_manager +) + +target_include_directories( + ${DEMO_NAME} + PUBLIC + "${CMAKE_CURRENT_LIST_DIR}" + "${LOGGING_INCLUDE_DIRS}" + ${OTA_INCLUDE_PUBLIC_DIRS} + ${OTA_INCLUDE_PRIVATE_DIRS} + ${OTA_INCLUDE_OS_POSIX_DIRS} + ${MQTT_INCLUDE_PUBLIC_DIRS} +) + +if(ROOT_CA_CERT_PATH) + target_compile_definitions( + ${DEMO_NAME} PRIVATE + ROOT_CA_CERT_PATH="${ROOT_CA_CERT_PATH}" + ) +endif() +if(BROKER_ENDPOINT) + target_compile_definitions( + ${DEMO_NAME} PRIVATE + BROKER_ENDPOINT="${BROKER_ENDPOINT}" + ) +endif() +if(CLIENT_IDENTIFIER) + target_compile_definitions( + ${DEMO_NAME} PRIVATE + CLIENT_IDENTIFIER="${CLIENT_IDENTIFIER}" + ) +endif() diff --git a/demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c b/demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c new file mode 100644 index 0000000000..47db704ede --- /dev/null +++ b/demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c @@ -0,0 +1,894 @@ +/* + * Copyright (C) 2020 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. + */ + +/** + * @file aws_iot_ota_update_demo.c + * @brief A simple OTA update example. + */ + +/* Standard includes. */ +#include +#include +#include + +/* Include Demo Config as the first non-system header. */ +#include "demo_config.h" + +/* OpenSSL sockets transport implementation. */ +#include "openssl_posix.h" + +/* Retry parameters. */ +#include "retry_utils.h" + +/* Clock for timer. */ +#include "clock.h" + +/* MQTT include. */ +#include "core_mqtt.h" +#include "mqtt_subscription_manager.h" + +/* OTA Library include. */ +#include "aws_iot_ota_agent.h" +#include "aws_ota_agent_config.h" +#include "aws_iot_ota_agent_private.h" + +/* OTA Library Interface include. */ +#include "ota_os_posix.h" +#include "ota_mqtt_interface.h" + +/* Include firmware version struct definition. */ +#include "iot_appversion32.h" + +/** + * @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT. + * + * This will be used if the AWS_MQTT_PORT is configured as 443 for AWS IoT MQTT broker. + * Please see more details about the ALPN protocol for AWS IoT MQTT endpoint + * in the link below. + * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ + */ +#define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca" + +/** + * @brief Length of ALPN protocol name. + */ +#define AWS_IOT_MQTT_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_MQTT_ALPN ) - 1 ) ) + +/** + * These configuration settings are required to run the OTA demo which uses mutual authentication. + * Throw compilation error if the below configs are not defined. + */ +#ifndef AWS_IOT_ENDPOINT + #error "Please define AWS IoT MQTT broker endpoint(AWS_IOT_ENDPOINT) in demo_config.h." +#endif +#ifndef ROOT_CA_CERT_PATH + #error "Please define path to Root CA certificate of the MQTT broker(ROOT_CA_CERT_PATH) in demo_config.h." +#endif +#ifndef CLIENT_IDENTIFIER + #error "Please define a unique client identifier, CLIENT_IDENTIFIER, in demo_config.h." +#endif +#ifndef CLIENT_CERT_PATH + #error "Please define path to client certificate(CLIENT_CERT_PATH) in demo_config.h." +#endif +#ifndef CLIENT_PRIVATE_KEY_PATH + #error "Please define path to client private key(CLIENT_PRIVATE_KEY_PATH) in demo_config.h." +#endif + +/** + * @brief Length of MQTT server host name. + */ +#define AWS_IOT_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_ENDPOINT ) - 1 ) ) + +/** + * @brief Length of client identifier. + */ +#define CLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( CLIENT_IDENTIFIER ) - 1 ) ) + +/** + * @brief Transport timeout in milliseconds for transport send and receive. + */ +#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 200 ) + +/** + * @brief Timeout for receiving CONNACK packet in milli seconds. + */ +#define CONNACK_RECV_TIMEOUT_MS ( 2000U ) + +/** + * @brief The maximum time interval in seconds which is allowed to elapse + * between two Control Packets. + * + * It is the responsibility of the Client to ensure that the interval between + * Control Packets being sent does not exceed the this Keep Alive value. In the + * absence of sending any other Control Packets, the Client MUST send a + * PINGREQ Packet. + */ +#define MQTT_KEEP_ALIVE_INTERVAL_SECONDS ( 60U ) + +/** + * @brief Timeout for MQTT_ProcessLoop function in milliseconds. + */ +#define MQTT_PROCESS_LOOP_TIMEOUT_MS ( 500U ) + +/** + * @brief Size of the network buffer to receive the MQTT message. + * + * The largest message size is data size from the AWS IoT streaming service, 2000 is reserved for + * extra headers. + */ +#define OTA_PRESIGNED_URL_MAX_SIZE ( 1500U ) +#define OTA_MQTT_HEADER_MAX_SIZE ( 30U ) +#define NETWORK_BUFFER_SIZE ( ( 1U << otaconfigLOG2_FILE_BLOCK_SIZE ) + \ + OTA_PRESIGNED_URL_MAX_SIZE + \ + OTA_MQTT_HEADER_MAX_SIZE ) + +/** + * @brief The delay used in the main OTA Demo task loop to periodically output the OTA + * statistics like number of packets received, dropped, processed and queued per connection. + */ +#define OTA_DEMO_TASK_DELAY_SECONDS ( 1U ) + +/*-----------------------------------------------------------*/ + +/** + * @brief Struct for firmware version. + */ +const AppVersion32_t appFirmwareVersion = +{ + .u.x.major = APP_VERSION_MAJOR, + .u.x.minor = APP_VERSION_MINOR, + .u.x.build = APP_VERSION_BUILD, +}; + +/** + * @brief The network buffer must remain valid when OTA library task is running. + */ +static uint8_t buffer[ NETWORK_BUFFER_SIZE ]; + +/** + * @brief Keep a flag for indicating if the MQTT connection is alive. + */ +static bool mqttSessionEstablished = false; + +/** + * @brief MQTT connection context used in this demo. + */ +static MQTTContext_t globalMqttContext; + +/*-----------------------------------------------------------*/ + +/* + * Publish a message to the specified client/topic at the given QOS. + */ + static OtaErr_t publish( const char * const pacTopic, + uint16_t topicLen, + const char * pMsg, + uint32_t msgSize, + uint8_t qos ); + + +static OtaErr_t subscribe( const char * pTopicFilter, + uint16_t topicFilterLength, + uint8_t qos, + void * pCallback ); + +static OtaErr_t unsubscribe( const char * pTopicFilter, + uint16_t topicFilterLength, + uint8_t qos ); + +/*-----------------------------------------------------------*/ + +/** + * @brief The OTA agent has completed the update job or it is in + * self test mode. If it was accepted, we want to activate the new image. + * This typically means we should reset the device to run the new firmware. + * If now is not a good time to reset the device, it may be activated later + * by your user code. If the update was rejected, just return without doing + * anything and we'll wait for another job. If it reported that we should + * start test mode, normally we would perform some kind of system checks to + * make sure our new firmware does the basic things we think it should do + * but we'll just go ahead and set the image as accepted for demo purposes. + * The accept function varies depending on your platform. Refer to the OTA + * PAL implementation for your platform in aws_ota_pal.c to see what it + * does for you. + * + * @param[in] event Specify if this demo is running with the AWS IoT + * MQTT server. Set this to `false` if using another MQTT server. + * @return None. + */ +static void App_OTACompleteCallback( OtaJobEvent_t event ) +{ + OtaErr_t err = OTA_ERR_UNINITIALIZED; + + /* OTA job is completed. so delete the MQTT and network connection. */ + if( event == OtaJobEventActivate ) + { + LogInfo( ( "Received OtaJobEventActivate callback from OTA Agent." ) ); + + /* OTA job is completed. so delete the network connection. */ + MQTT_Disconnect( &globalMqttContext ); + + /* Activate the new firmware image. */ + OTA_ActivateNewImage(); + + /* We should never get here as new image activation must reset the device.*/ + LogError( ( "New image activation failed." ) ); + + for( ; ; ) + { + } + } + else if( event == OtaJobEventFail ) + { + LogInfo( ( "Received OtaJobEventFail callback from OTA Agent." ) ); + + /* Nothing special to do. The OTA agent handles it. */ + } + else if( event == OtaJobEventStartTest ) + { + /* This demo just accepts the image since it was a good OTA update and networking + * and services are all working (or we wouldn't have made it this far). If this + * were some custom device that wants to test other things before calling it OK, + * this would be the place to kick off those tests before calling OTA_SetImageState() + * with the final result of either accepted or rejected. */ + + LogInfo( ( "Received OtaJobEventStartTest callback from OTA Agent." ) ); + err = OTA_SetImageState( OtaImageStateAccepted ); + + if( err != OTA_ERR_NONE ) + { + LogError( ( " Error! Failed to set image state as accepted." ) ); + } + } +} + +/*-----------------------------------------------------------*/ + +static void jobCallback( MQTTContext_t * pContext, MQTTPublishInfo_t * pPublishInfo ) +{ + // static char buff[1024]; + assert( pPublishInfo != NULL ); + assert( pContext != NULL ); + + OtaEventData_t * pData; + OtaEventMsg_t eventMsg = { 0 }; + + /* Suppress unused parameter warning when asserts are disabled in build. */ + ( void ) pContext; + + + // TODO, notify OTA agent about the incoming message. + + LogInfo( ( "Received ota message callback.\n\n" ) ); + + pData = otaEventBufferGet(); + + + if( pData != NULL ) + { + memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); + pData->dataLength = pPublishInfo->payloadLength ; + eventMsg.eventId = OtaAgentEventReceivedJobDocument; + eventMsg.pEventData = pData; + + /* Send job document received event. */ + OTA_SignalEvent( &eventMsg ); + } + else + { + OTA_LOG_L1( "Error: No OTA data buffers available.\r\n" ); + } + +} + +/*-----------------------------------------------------------*/ + +static void dataCallback( MQTTContext_t * pContext, MQTTPublishInfo_t * pPublishInfo ) +{ + // static char buff[1024]; + assert( pPublishInfo != NULL ); + assert( pContext != NULL ); + + OtaEventData_t * pData; + OtaEventMsg_t eventMsg = { 0 }; + + /* Suppress unused parameter warning when asserts are disabled in build. */ + ( void ) pContext; + + // memcpy( buff, pPublishInfo->pPayload, pPublishInfo->payloadLength ); + + // TODO, notify OTA agent about the incoming message. + + LogInfo( ( "Received ota message callback.\n\n" ) ); + + pData = otaEventBufferGet(); + + + if( pData != NULL ) + { + memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); + pData->dataLength = pPublishInfo->payloadLength ; + eventMsg.eventId = OtaAgentEventReceivedFileBlock; + eventMsg.pEventData = pData; + + /* Send job document received event. */ + OTA_SignalEvent( &eventMsg ); + } + else + { + OTA_LOG_L1( "Error: No OTA data buffers available.\r\n" ); + } +} + +/*-----------------------------------------------------------*/ + +static void mqttEventCallback( MQTTContext_t * pMqttContext, + MQTTPacketInfo_t * pPacketInfo, + MQTTDeserializedInfo_t * pDeserializedInfo ) +{ + assert( pMqttContext != NULL ); + assert( pPacketInfo != NULL ); + assert( pDeserializedInfo != NULL ); + // assert( pDeserializedInfo->packetIdentifier != MQTT_PACKET_ID_INVALID ); + + /* Handle incoming publish. The lower 4 bits of the publish packet + * type is used for the dup, QoS, and retain flags. Hence masking + * out the lower bits to check if the packet is publish. */ + if( ( pPacketInfo->type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH ) + { + assert( pDeserializedInfo->pPublishInfo != NULL ); + /* Handle incoming publish. */ + SubscriptionManager_DispatchHandler( pMqttContext, pDeserializedInfo->pPublishInfo ); + } + else + { + /* Handle other packets. */ + switch( pPacketInfo->type ) + { + case MQTT_PACKET_TYPE_SUBACK: + LogInfo( ( "Received SUBACK.\n\n" ) ); + // TODO, handle suback for OTA. + break; + + case MQTT_PACKET_TYPE_UNSUBACK: + LogInfo( ( "Received UNSUBACK.\n\n" ) ); + // TODO, handle ubsuback for OTA. + break; + + case MQTT_PACKET_TYPE_PINGRESP: + /* Nothing to be done from application as library handles + * PINGRESP. */ + LogWarn( ( "PINGRESP should not be handled by the application " + "callback when using MQTT_ProcessLoop.\n\n" ) ); + break; + + case MQTT_PACKET_TYPE_PUBACK: + LogInfo( ( "PUBACK received for packet id %u.\n\n", + pDeserializedInfo->packetIdentifier ) ); + break; + + /* Any other packet type is invalid. */ + default: + LogError( ( "Unknown packet type received:(%02x).\n\n", + pPacketInfo->type ) ); + } + } +} + +/*-----------------------------------------------------------*/ + +static int connectToServerWithBackoffRetries( NetworkContext_t * pNetworkContext ) +{ + int returnStatus = EXIT_SUCCESS; + RetryUtilsStatus_t retryUtilsStatus = RetryUtilsSuccess; + OpensslStatus_t opensslStatus = OPENSSL_SUCCESS; + RetryUtilsParams_t reconnectParams; + ServerInfo_t serverInfo; + OpensslCredentials_t opensslCredentials; + + /* Initialize information to connect to the MQTT broker. */ + serverInfo.pHostName = AWS_IOT_ENDPOINT; + serverInfo.hostNameLength = AWS_IOT_ENDPOINT_LENGTH; + serverInfo.port = AWS_MQTT_PORT; + + /* Initialize credentials for establishing TLS session. */ + memset( &opensslCredentials, 0, sizeof( OpensslCredentials_t ) ); + opensslCredentials.pRootCaPath = ROOT_CA_CERT_PATH; + + /* If #CLIENT_USERNAME is defined, username/password is used for authenticating + * the client. */ + #ifndef CLIENT_USERNAME + opensslCredentials.pClientCertPath = CLIENT_CERT_PATH; + opensslCredentials.pPrivateKeyPath = CLIENT_PRIVATE_KEY_PATH; + #endif + + /* AWS IoT requires devices to send the Server Name Indication (SNI) + * extension to the Transport Layer Security (TLS) protocol and provide + * the complete endpoint address in the host_name field. Details about + * SNI for AWS IoT can be found in the link below. + * https://docs.aws.amazon.com/iot/latest/developerguide/transport-security.html */ + opensslCredentials.sniHostName = AWS_IOT_ENDPOINT; + + if( AWS_MQTT_PORT == 443 ) + { + /* Pass the ALPN protocol name depending on the port being used. + * Please see more details about the ALPN protocol for the AWS IoT MQTT + * endpoint in the link below. + * https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/ + * + * For username and password based authentication in AWS IoT, + * #AWS_IOT_PASSWORD_ALPN is used. More details can be found in the + * link below. + * https://docs.aws.amazon.com/iot/latest/developerguide/enhanced-custom-auth-using.html + */ + #ifdef CLIENT_USERNAME + opensslCredentials.pAlpnProtos = AWS_IOT_PASSWORD_ALPN; + opensslCredentials.alpnProtosLen = AWS_IOT_PASSWORD_ALPN_LENGTH; + #else + opensslCredentials.pAlpnProtos = AWS_IOT_MQTT_ALPN; + opensslCredentials.alpnProtosLen = AWS_IOT_MQTT_ALPN_LENGTH; + #endif + } + + /* Initialize reconnect attempts and interval */ + RetryUtils_ParamsReset( &reconnectParams ); + + /* Attempt to connect to MQTT broker. If connection fails, retry after + * a timeout. Timeout value will exponentially increase until maximum + * attempts are reached. + */ + do + { + /* Establish a TLS session with the MQTT broker. This example connects + * to the MQTT broker as specified in AWS_IOT_ENDPOINT and AWS_MQTT_PORT + * at the demo config header. */ + LogInfo( ( "Establishing a TLS session to %.*s:%d.", + AWS_IOT_ENDPOINT_LENGTH, + AWS_IOT_ENDPOINT, + AWS_MQTT_PORT ) ); + opensslStatus = Openssl_Connect( pNetworkContext, + &serverInfo, + &opensslCredentials, + TRANSPORT_SEND_RECV_TIMEOUT_MS, + TRANSPORT_SEND_RECV_TIMEOUT_MS ); + + if( opensslStatus != OPENSSL_SUCCESS ) + { + LogWarn( ( "Connection to the broker failed. Retrying connection with backoff and jitter." ) ); + retryUtilsStatus = RetryUtils_BackoffAndSleep( &reconnectParams ); + } + + if( retryUtilsStatus == RetryUtilsRetriesExhausted ) + { + LogError( ( "Connection to the broker failed, all attempts exhausted." ) ); + returnStatus = EXIT_FAILURE; + } + } while( ( opensslStatus != OPENSSL_SUCCESS ) && ( retryUtilsStatus == RetryUtilsSuccess ) ); + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +static int establishMqttSession( MQTTContext_t * pMqttContext, + NetworkContext_t * pNetworkContext, + bool createCleanSession, + bool * pSessionPresent ) +{ + int returnStatus = EXIT_SUCCESS; + MQTTStatus_t mqttStatus; + MQTTConnectInfo_t connectInfo; + MQTTFixedBuffer_t networkBuffer; + TransportInterface_t transport; + + assert( pMqttContext != NULL ); + assert( pNetworkContext != NULL ); + + /* Fill in TransportInterface send and receive function pointers. + * For this demo, TCP sockets are used to send and receive data + * from network. Network context is SSL context for OpenSSL.*/ + transport.pNetworkContext = pNetworkContext; + transport.send = Openssl_Send; + transport.recv = Openssl_Recv; + + /* Fill the values for network buffer. */ + networkBuffer.pBuffer = buffer; + networkBuffer.size = NETWORK_BUFFER_SIZE; + + /* Initialize MQTT library. */ + mqttStatus = MQTT_Init( pMqttContext, + &transport, + Clock_GetTimeMs, + mqttEventCallback, + &networkBuffer ); + + if( mqttStatus != MQTTSuccess ) + { + returnStatus = EXIT_FAILURE; + LogError( ( "MQTT init failed with status %s.", MQTT_Status_strerror( mqttStatus ) ) ); + } + else + { + /* Establish MQTT session by sending a CONNECT packet. */ + + /* If #createCleanSession is true, start with a clean session + * i.e. direct the MQTT broker to discard any previous session data. + * If #createCleanSession is false, directs the broker to attempt to + * reestablish a session which was already present. */ + connectInfo.cleanSession = createCleanSession; + + /* The client identifier is used to uniquely identify this MQTT client to + * the MQTT broker. In a production device the identifier can be something + * unique, such as a device serial number. */ + connectInfo.pClientIdentifier = CLIENT_IDENTIFIER; + connectInfo.clientIdentifierLength = CLIENT_IDENTIFIER_LENGTH; + + /* The maximum time interval in seconds which is allowed to elapse + * between two Control Packets. + * It is the responsibility of the Client to ensure that the interval between + * Control Packets being sent does not exceed the this Keep Alive value. In the + * absence of sending any other Control Packets, the Client MUST send a + * PINGREQ Packet. */ + connectInfo.keepAliveSeconds = MQTT_KEEP_ALIVE_INTERVAL_SECONDS; + + /* Username and password for authentication. Not used in this demo. */ + connectInfo.pUserName = NULL; + connectInfo.userNameLength = 0U; + connectInfo.pPassword = NULL; + connectInfo.passwordLength = 0U; + + /* Send MQTT CONNECT packet to broker. */ + mqttStatus = MQTT_Connect( pMqttContext, &connectInfo, NULL, CONNACK_RECV_TIMEOUT_MS, pSessionPresent ); + + if( mqttStatus != MQTTSuccess ) + { + returnStatus = EXIT_FAILURE; + LogError( ( "Connection with MQTT broker failed with status %u.", mqttStatus ) ); + } + else + { + LogInfo( ( "MQTT connection successfully established with broker.\n\n" ) ); + } + } + + return returnStatus; +} + +/*-----------------------------------------------------------*/ + +static OtaErr_t subscribe( const char * pTopicFilter, + uint16_t topicFilterLength, + uint8_t qos, + void * pCallback ) +{ + int returnStatus = EXIT_SUCCESS; + MQTTStatus_t mqttStatus; + MQTTContext_t * pMqttContext = &globalMqttContext; + MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; + + assert( pMqttContext != NULL ); + assert( pTopicFilter != NULL ); + assert( topicFilterLength > 0 ); + + /* Start with everything at 0. */ + ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); + + /* This example subscribes to only one topic and uses QOS1. */ + pSubscriptionList[ 0 ].qos = qos; + pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; + pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; + + /* Send SUBSCRIBE packet. */ + mqttStatus = MQTT_Subscribe( pMqttContext, + pSubscriptionList, + sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), + MQTT_GetPacketId( pMqttContext ) ); + + if( mqttStatus != MQTTSuccess ) + { + LogError( ( "Failed to send SUBSCRIBE packet to broker with error = %u.", + mqttStatus ) ); + returnStatus = EXIT_FAILURE; + } + else + { + LogInfo( ( "SUBSCRIBE topic %.*s to broker.\n\n", + topicFilterLength, + pTopicFilter) ); + + /* Process incoming packet from the broker. Acknowledgment for subscription + * ( SUBACK ) will be received here. However after sending the subscribe, the + * client may receive a publish before it receives a subscribe ack. Since this + * demo is subscribing to the topic to which no one is publishing, probability + * of receiving publish message before subscribe ack is zero; but application + * must be ready to receive any packet. This demo uses MQTT_ProcessLoop to + * receive packet from network. */ + mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); + + if( mqttStatus != MQTTSuccess ) + { + returnStatus = EXIT_FAILURE; + LogError( ( "MQTT_ProcessLoop returned with status = %u.", + mqttStatus ) ); + } + } + + /* Register callback to suncription manager. */ + SubscriptionManager_RegisterCallback( pTopicFilter, topicFilterLength, pCallback ); + + return returnStatus; +} + +/* + * Publish a message to the specified client/topic at the given QOS. + */ + static OtaErr_t publish( const char * const pacTopic, + uint16_t topicLen, + const char * pMsg, + uint32_t msgSize, + uint8_t qos ) +{ + OtaErr_t otaErrRet = OTA_ERR_UNINITIALIZED; + + MQTTStatus_t mqttStatus = MQTTBadParameter; + MQTTPublishInfo_t publishInfo; + MQTTContext_t * pMqttContext = &globalMqttContext; + + publishInfo.pTopicName = pacTopic; + publishInfo.topicNameLength = topicLen; + publishInfo.qos = qos; + publishInfo.pPayload = pMsg; + publishInfo.payloadLength = msgSize; + + mqttStatus = MQTT_Publish( pMqttContext, + &publishInfo, + MQTT_GetPacketId( pMqttContext ) ); + + if( mqttStatus == MQTTSuccess ) + { + /* Wait for the publish to complete. */ + mqttStatus = MQTT_ProcessLoop( pMqttContext, MQTT_PROCESS_LOOP_TIMEOUT_MS ); + + if( mqttStatus != MQTTSuccess ) + { + LogError( ( " Publish ack wait failed with error = %u.", mqttStatus ) ); + + otaErrRet = OTA_ERR_PUBLISH_FAILED; + } + else + { + LogInfo( ( " Publish success.\n\r" ) ); + + otaErrRet = OTA_ERR_NONE; + } + + } + else + { + LogError( ( "Failed to send PUBLISH packet to broker with error = %u.", mqttStatus ) ); + + otaErrRet = OTA_ERR_PUBLISH_FAILED; + } + + return otaErrRet; +} + +static OtaErr_t unsubscribe( const char * pTopicFilter, + uint16_t topicFilterLength, + uint8_t qos ) +{ + int returnStatus = EXIT_SUCCESS; + MQTTStatus_t mqttStatus; + + MQTTSubscribeInfo_t pSubscriptionList[ 1 ]; + MQTTContext_t * pMqttContext = &globalMqttContext; + + /* Start with everything at 0. */ + ( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) ); + + /* This example subscribes to and unsubscribes from only one topic + * and uses QOS1. */ + pSubscriptionList[ 0 ].qos = qos; + pSubscriptionList[ 0 ].pTopicFilter = pTopicFilter; + pSubscriptionList[ 0 ].topicFilterLength = topicFilterLength; + + /* Send UNSUBSCRIBE packet. */ + mqttStatus = MQTT_Unsubscribe( pMqttContext, + pSubscriptionList, + sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ), + MQTT_GetPacketId( pMqttContext ) ); + + if( mqttStatus != MQTTSuccess ) + { + LogError( ( "Failed to send UNSUBSCRIBE packet to broker with error = %s.", + MQTT_Status_strerror( mqttStatus ) ) ); + returnStatus = EXIT_FAILURE; + } + else + { + /* Process Incoming UNSUBACK packet from the broker. */ + mqttStatus = MQTT_ProcessLoop( pMqttContext, MQTT_PROCESS_LOOP_TIMEOUT_MS ); + + if( mqttStatus != MQTTSuccess ) + { + returnStatus = EXIT_FAILURE; + LogError( ( "MQTT_ProcessLoop returned with status = %s.", + MQTT_Status_strerror( mqttStatus ) ) ); + } + } + + return returnStatus; +} + + +/*-----------------------------------------------------------*/ + +void startOTADemo( MQTTContext_t * pMqttContext ) +{ + int ret = 0; + + MQTTStatus_t mqttStatus; + + OtaEventMsg_t eventMsg = { 0 }; + + /* MQTT susbsrciption manager parameters.*/ + SubscriptionManagerStatus_t mqttManagerStatus = 0u; + MQTTSubscribeInfo_t subscriptionInfo; + uint16_t topicLen = 0; + size_t subscriptionCount = 1; + + /* OTA Agent state.*/ + OtaState_t state = OtaAgentStateStopped; + + /* Initialize OTA library OS Interface. */ + static OtaOSInterface_t otaOSInterface; + otaOSInterface.event.init = ota_InitEvent; + otaOSInterface.event.send = ota_SendEvent; + otaOSInterface.event.recv = ota_ReceiveEvent; + otaOSInterface.event.deinit = ota_DeinitEvent; + + /* Intialize the OTA library MQTT Interface.*/ + static OtaMqttInterface_t otaMqttInterface; + otaMqttInterface.subscribe = subscribe; + otaMqttInterface.publish = publish; + otaMqttInterface.unsubscribe = unsubscribe; + otaMqttInterface.jobCallback = jobCallback; + otaMqttInterface.dataCallback= dataCallback; + + /* OTA Agent thread handle. */ + pthread_t threadHandle; + + /* Initialize the OTA Agent , if it is resuming the OTA statistics will be cleared for new + * connection.*/ + OTA_AgentInit( ( void * ) ( pMqttContext ), + &otaOSInterface, + &otaMqttInterface, + ( const uint8_t * ) ( CLIENT_IDENTIFIER ), + App_OTACompleteCallback, + ( uint32_t ) ~0 ); + + sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + + /* Create the OTA Agent thread with default attributes.*/ + pthread_create( &threadHandle, NULL, otaAgentTask, NULL ); + + eventMsg.eventId = OtaAgentEventStart; + OTA_SignalEvent( &eventMsg ); + + /* Wait forever for OTA traffic but allow other tasks to run and output statistics only once + * per second. */ + while( ( ( state = OTA_GetAgentState() ) != OtaAgentStateStopped ) ) + { + LogInfo( ( " Received: %u Queued: %u Processed: %u Dropped: %u", + OTA_GetPacketsReceived(), + OTA_GetPacketsQueued(), + OTA_GetPacketsProcessed(), + OTA_GetPacketsDropped() ) ); + + sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + + // if(state == OtaAgentStateWaitingForJob ) + // { + // mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); + + // if( mqttStatus != MQTTSuccess ) + // { + // LogError( ( "MQTT_ProcessLoop returned with status = %u.", + // mqttStatus ) ); + // } + // } + // else + // { + // sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + // } + + } + +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point of demo. + * + * This example initializes the OTA agent to enable OTA updates via the + * MQTT broker. It simply connects to the MQTT broker with the users + * credentials and spins in an indefinite loop to allow MQTT messages to be + * forwarded to the OTA agent for possible processing. The OTA agent does all + * of the real work; checking to see if the message topic is one destined for + * the OTA agent. If not, it is simply ignored. + */ +int main( int argc, + char ** argv ) +{ + ( void ) argc; + ( void ) argv; + + int returnStatus = EXIT_SUCCESS; + NetworkContext_t networkContext; + bool mqttSessionPresent = false; + + LogInfo( ( "OTA over MQTT demo version %u.%u.%u", + appFirmwareVersion.u.x.major, + appFirmwareVersion.u.x.minor, + appFirmwareVersion.u.x.build ) ); + + for( ; ; ) + { + /* Attempt to connect to the MQTT broker. If connection fails, retry after + * a timeout. Timeout value will be exponentially increased till the maximum + * attempts are reached or maximum timeout value is reached. The function + * returns EXIT_FAILURE if the TCP connection cannot be established to + * broker after configured number of attempts. */ + returnStatus = connectToServerWithBackoffRetries( &networkContext ); + + if( returnStatus == EXIT_FAILURE ) + { + /* Log error to indicate connection failure after all + * reconnect attempts are over. */ + LogError( ( "Failed to connect to MQTT broker %.*s.", + AWS_IOT_ENDPOINT_LENGTH, + AWS_IOT_ENDPOINT ) ); + } + else + { + /* Sends an MQTT Connect packet to establish a clean connection over the + * established TLS session, then waits for connection acknowledgment + * (CONNACK) packet. */ + if( EXIT_SUCCESS == establishMqttSession( &globalMqttContext, + &networkContext, + true, /* clean session */ + &mqttSessionPresent ) ) + { + mqttSessionEstablished = true; + } + + } + + if( mqttSessionEstablished ) + { + /* If TLS session is established, start the OTA agent. */ + startOTADemo( &globalMqttContext ); + } + } + + return returnStatus; +} diff --git a/demos/ota/ota_demo_mqtt/aws_ota_agent_config.h b/demos/ota/ota_demo_mqtt/aws_ota_agent_config.h new file mode 100644 index 0000000000..31324026ab --- /dev/null +++ b/demos/ota/ota_demo_mqtt/aws_ota_agent_config.h @@ -0,0 +1,175 @@ +/* + * FreeRTOS V1.4.7 + * Copyright (C) 2020 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 + */ + +/** + * @file aws_ota_agent_config.h + * @brief OTA user configurable settings. + */ + +#ifndef _AWS_OTA_AGENT_CONFIG_H_ +#define _AWS_OTA_AGENT_CONFIG_H_ + +/**************************************************/ +/******* DO NOT CHANGE the following order ********/ +/**************************************************/ + +/* Logging related header files are required to be included in the following order: + * 1. Include the header file "logging_levels.h". + * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. + * 3. Include the header file "logging_stack.h". + */ + +/* Include header that defines log levels. */ +#include "logging_levels.h" + +/* Configure name and log level for the MQTT library. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "MQTT" +#endif +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_INFO +#endif + +#include "logging_stack.h" + +/************ End of logging configuration ****************/ + +/** + * @brief The number of words allocated to the stack for the OTA agent. + */ +#define otaconfigSTACK_SIZE 10000U + +/** + * @brief Log base 2 of the size of the file data block message (excluding the header). + * + * 10 bits yields a data block size of 1KB. + */ +#define otaconfigLOG2_FILE_BLOCK_SIZE 14UL + +/** + * @brief Milliseconds to wait for the self test phase to succeed before we force reset. + */ +#define otaconfigSELF_TEST_RESPONSE_WAIT_MS 16000U + +/** + * @brief Milliseconds to wait before requesting data blocks from the OTA service if nothing is happening. + * + * The wait timer is reset whenever a data block is received from the OTA service so we will only send + * the request message after being idle for this amount of time. + */ +#define otaconfigFILE_REQUEST_WAIT_MS 10000U + +/** + * @brief The OTA agent task priority. Normally it runs at a low priority. + */ +#define otaconfigAGENT_PRIORITY tskIDLE_PRIORITY + 5U + +/** + * @brief The maximum allowed length of the thing name used by the OTA agent. + * + * AWS IoT requires Thing names to be unique for each device that connects to the broker. + * Likewise, the OTA agent requires the developer to construct and pass in the Thing name when + * initializing the OTA agent. The agent uses this size to allocate static storage for the + * Thing name used in all OTA base topics. Namely $aws/things/ + */ +#define otaconfigMAX_THINGNAME_LEN 64U +/** + * @brief The maximum number of data blocks requested from OTA streaming service. + * + * This configuration parameter is sent with data requests and represents the maximum number of + * data blocks the service will send in response. The maximum limit for this must be calculated + * from the maximum data response limit (128 KB from service) divided by the block size. + * For example if block size is set as 1 KB then the maximum number of data blocks that we can + * request is 128/1 = 128 blocks. Configure this parameter to this maximum limit or lower based on + * how many data blocks response is expected for each data requests. + * Please note that this must be set larger than zero. + * + */ +#define otaconfigMAX_NUM_BLOCKS_REQUEST 1U + +/** + * @brief The maximum number of requests allowed to send without a response before we abort. + * + * This configuration parameter sets the maximum number of times the requests are made over + * the selected communication channel before aborting and returning error. + * + */ +#define otaconfigMAX_NUM_REQUEST_MOMENTUM 32U + +/** + * @brief The number of data buffers reserved by the OTA agent. + * + * This configurations parameter sets the maximum number of static data buffers used by + * the OTA agent for job and file data blocks received. + */ +#define otaconfigMAX_NUM_OTA_DATA_BUFFERS 1U + +/** + * @brief Allow update to same or lower version. + * + * Set this to 1 to allow downgrade or same version update.This configurations parameter + * disables version check and allows update to a same or lower version.This is provided for + * testing purpose and it is recommended to always update to higher version and keep this + * configuration disabled. + */ +#define otaconfigAllowDowngrade 0U + +/** + * @brief The protocol selected for OTA control operations. + + * This configurations parameter sets the default protocol for all the OTA control + * operations like requesting OTA job, updating the job status etc. + * + * Note - Only MQTT is supported at this time for control operations. + */ +#define configENABLED_CONTROL_PROTOCOL ( OTA_CONTROL_OVER_MQTT ) + +/** + * @brief The protocol selected for OTA data operations. + + * This configurations parameter sets the protocols selected for the data operations + * like requesting file blocks from the service. + * + * Note - Both MQTT and HTTP is supported for data transfer. This configuration parameter + * can be set to following - + * Enable data over MQTT - ( OTA_DATA_OVER_MQTT ) + * Enable data over HTTP - ( OTA_DATA_OVER_HTTP) + * Enable data over both MQTT & HTTP ( OTA_DATA_OVER_MQTT | OTA_DATA_OVER_HTTP ) + */ +#define configENABLED_DATA_PROTOCOLS ( OTA_DATA_OVER_MQTT ) + + /** + * @brief The preferred protocol selected for OTA data operations. + * + * Primary data protocol will be the protocol used for downloading file if more than + * one protocol is selected while creating OTA job. Default primary data protocol is MQTT + * and following update here to switch to HTTP as primary. + * + * Note - use OTA_DATA_OVER_HTTP for HTTP as primary data protocol. + */ + +#define configOTA_PRIMARY_DATA_PROTOCOL ( OTA_DATA_OVER_MQTT ) + +#endif /* _AWS_OTA_AGENT_CONFIG_H_ */ diff --git a/demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h b/demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h new file mode 100644 index 0000000000..905407ca21 --- /dev/null +++ b/demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h @@ -0,0 +1,39 @@ +/* + * FreeRTOS V202007.00 + * Copyright (C) 2020 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 + */ + +#ifndef __AWS_CODESIGN_KEYS__H__ +#define __AWS_CODESIGN_KEYS__H__ + +/* + * PEM-encoded code signer certificate + * + * Must include the PEM header and footer: + * "-----BEGIN CERTIFICATE-----\n" + * "...base64 data...\n" + * "-----END CERTIFICATE-----\n"; + */ +static const char signingcredentialSIGNING_CERTIFICATE_PEM[] = "Paste code signing certificate here."; + +#endif diff --git a/demos/ota/ota_demo_mqtt/demo_config.h b/demos/ota/ota_demo_mqtt/demo_config.h new file mode 100644 index 0000000000..5dd7926f58 --- /dev/null +++ b/demos/ota/ota_demo_mqtt/demo_config.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 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. + */ + +#ifndef DEMO_CONFIG_H_ +#define DEMO_CONFIG_H_ + +/**************************************************/ +/******* DO NOT CHANGE the following order ********/ +/**************************************************/ + +/* Logging related header files are required to be included in the following order: + * 1. Include the header file "logging_levels.h". + * 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL. + * 3. Include the header file "logging_stack.h". + */ + +/* Include header that defines log levels. */ +#include "logging_levels.h" + +/* Logging configuration for the Demo. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "DEMO" +#endif +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_DEBUG +#endif + +#include "logging_stack.h" + +/************ End of logging configuration ****************/ + +/** + * @brief Details of the MQTT broker to connect to. + * + * @note Your AWS IoT Core endpoint can be found in the AWS IoT console under + * Settings/Custom Endpoint, or using the describe-endpoint API. + * + * #define AWS_IOT_ENDPOINT "...insert here..." + */ +#define AWS_IOT_ENDPOINT "" + +/** + * @brief AWS IoT MQTT broker port number. + * + * In general, port 8883 is for secured MQTT connections. + * + * @note Port 443 requires use of the ALPN TLS extension with the ALPN protocol + * name. When using port 8883, ALPN is not required. + */ +#define AWS_MQTT_PORT ( 8883 ) + +/** + * @brief Path of the file containing the server's root CA certificate. + * + * This certificate is used to identify the AWS IoT server and is publicly + * available. Refer to the AWS documentation available in the link below + * https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs + * + * Amazon's root CA certificate is automatically downloaded to the certificates + * directory from @ref https://www.amazontrust.com/repository/AmazonRootCA1.pem + * using the CMake build system. + * + * @note This certificate should be PEM-encoded. + * @note This path is relative from the demo binary created. Update + * ROOT_CA_CERT_PATH to the absolute path if this demo is executed from elsewhere. + */ +#ifndef ROOT_CA_CERT_PATH + #define ROOT_CA_CERT_PATH "/home/ubuntu/dev/aws-iot-device-sdk-embedded-C-staging/demos/certificates/AmazonRootCA1.crt" +#endif + +/** + * @brief Path of the file containing the client certificate. + * + * Refer to the AWS documentation below for details regarding client + * authentication. + * https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html + * + * @note This certificate should be PEM-encoded. + * + * #define CLIENT_CERT_PATH "...insert here..." + */ +/** + * @brief Path of the file containing the client's private key. + * + * Refer to the AWS documentation below for details regarding client + * authentication. + * https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html + * + * @note This private key should be PEM-encoded. + * + * #define CLIENT_PRIVATE_KEY_PATH "...insert here..." + */ +/** + * @brief MQTT client identifier. + * + * No two clients may use the same client identifier simultaneously. + */ +#ifndef CLIENT_IDENTIFIER + #define CLIENT_IDENTIFIER "testclient" +#endif + +/** + * @brief Configure application version. + */ + +#define APP_VERSION_MAJOR 0 +#define APP_VERSION_MINOR 9 +#define APP_VERSION_BUILD 2 + +#endif /* ifndef DEMO_CONFIG_H */ From b6937986c88212a199e35270f7afc0c19a84114c Mon Sep 17 00:00:00 2001 From: Shubham Divekar Date: Wed, 21 Oct 2020 21:51:38 +0000 Subject: [PATCH 2/2] renaming demos --- .../CMakeLists.txt | 4 +-- .../aws_ota_agent_config.h | 0 .../aws_ota_codesigner_certificate.h | 0 .../demo_config.h | 2 +- .../ota_demo_core_http.c} | 30 +++++++++---------- .../CMakeLists.txt | 4 +-- .../aws_ota_agent_config.h | 0 .../aws_ota_codesigner_certificate.h | 0 .../demo_config.h | 2 +- .../ota_demo_core_mqtt.c} | 30 +++++++++---------- 10 files changed, 34 insertions(+), 38 deletions(-) rename demos/ota/{ota_demo_http => ota_demo_core_http}/CMakeLists.txt (95%) rename demos/ota/{ota_demo_http => ota_demo_core_http}/aws_ota_agent_config.h (100%) rename demos/ota/{ota_demo_http => ota_demo_core_http}/aws_ota_codesigner_certificate.h (100%) rename demos/ota/{ota_demo_mqtt => ota_demo_core_http}/demo_config.h (97%) rename demos/ota/{ota_demo_http/aws_iot_ota_update_demo.c => ota_demo_core_http/ota_demo_core_http.c} (98%) rename demos/ota/{ota_demo_mqtt => ota_demo_core_mqtt}/CMakeLists.txt (95%) rename demos/ota/{ota_demo_mqtt => ota_demo_core_mqtt}/aws_ota_agent_config.h (100%) rename demos/ota/{ota_demo_mqtt => ota_demo_core_mqtt}/aws_ota_codesigner_certificate.h (100%) rename demos/ota/{ota_demo_http => ota_demo_core_mqtt}/demo_config.h (97%) rename demos/ota/{ota_demo_mqtt/aws_iot_ota_update_demo.c => ota_demo_core_mqtt/ota_demo_core_mqtt.c} (98%) diff --git a/demos/ota/ota_demo_http/CMakeLists.txt b/demos/ota/ota_demo_core_http/CMakeLists.txt similarity index 95% rename from demos/ota/ota_demo_http/CMakeLists.txt rename to demos/ota/ota_demo_core_http/CMakeLists.txt index 49b4be9f9e..a0f13d8f2c 100644 --- a/demos/ota/ota_demo_http/CMakeLists.txt +++ b/demos/ota/ota_demo_core_http/CMakeLists.txt @@ -1,4 +1,4 @@ -set( DEMO_NAME "ota_demo_http" ) +set( DEMO_NAME "ota_demo_core_http" ) # Include required library's source and header path variables. include( ${CMAKE_SOURCE_DIR}/libraries/aws/ota/otaFilePaths.cmake ) @@ -13,7 +13,7 @@ find_library(LIB_RT rt REQUIRED) target_sources( ${DEMO_NAME} PRIVATE - "aws_iot_ota_update_demo.c" + "ota_demo_core_http.c" ${OTA_SOURCES} ${OTA_OS_POSIX_SOURCES} ${OTA_MQTT_SOURCES} diff --git a/demos/ota/ota_demo_http/aws_ota_agent_config.h b/demos/ota/ota_demo_core_http/aws_ota_agent_config.h similarity index 100% rename from demos/ota/ota_demo_http/aws_ota_agent_config.h rename to demos/ota/ota_demo_core_http/aws_ota_agent_config.h diff --git a/demos/ota/ota_demo_http/aws_ota_codesigner_certificate.h b/demos/ota/ota_demo_core_http/aws_ota_codesigner_certificate.h similarity index 100% rename from demos/ota/ota_demo_http/aws_ota_codesigner_certificate.h rename to demos/ota/ota_demo_core_http/aws_ota_codesigner_certificate.h diff --git a/demos/ota/ota_demo_mqtt/demo_config.h b/demos/ota/ota_demo_core_http/demo_config.h similarity index 97% rename from demos/ota/ota_demo_mqtt/demo_config.h rename to demos/ota/ota_demo_core_http/demo_config.h index 5dd7926f58..a6dc6a9e9b 100644 --- a/demos/ota/ota_demo_mqtt/demo_config.h +++ b/demos/ota/ota_demo_core_http/demo_config.h @@ -83,7 +83,7 @@ * ROOT_CA_CERT_PATH to the absolute path if this demo is executed from elsewhere. */ #ifndef ROOT_CA_CERT_PATH - #define ROOT_CA_CERT_PATH "/home/ubuntu/dev/aws-iot-device-sdk-embedded-C-staging/demos/certificates/AmazonRootCA1.crt" + #define ROOT_CA_CERT_PATH "certificates/AmazonRootCA1.crt" #endif /** diff --git a/demos/ota/ota_demo_http/aws_iot_ota_update_demo.c b/demos/ota/ota_demo_core_http/ota_demo_core_http.c similarity index 98% rename from demos/ota/ota_demo_http/aws_iot_ota_update_demo.c rename to demos/ota/ota_demo_core_http/ota_demo_core_http.c index 723815a7d6..f6c9331a7e 100644 --- a/demos/ota/ota_demo_http/aws_iot_ota_update_demo.c +++ b/demos/ota/ota_demo_core_http/ota_demo_core_http.c @@ -20,7 +20,7 @@ */ /** - * @file aws_iot_ota_update_demo.c + * @file ota_demo_core_http.c * @brief A simple OTA update example. */ @@ -788,22 +788,20 @@ void startOTADemo( MQTTContext_t * pMqttContext ) OTA_GetPacketsProcessed(), OTA_GetPacketsDropped() ) ); - sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + if(state == OtaAgentStateWaitingForJob ) + { + mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); - // if(state == OtaAgentStateWaitingForJob ) - // { - // mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); - - // if( mqttStatus != MQTTSuccess ) - // { - // LogError( ( "MQTT_ProcessLoop returned with status = %u.", - // mqttStatus ) ); - // } - // } - // else - // { - // sleep( OTA_DEMO_TASK_DELAY_SECONDS ); - // } + if( mqttStatus != MQTTSuccess ) + { + LogError( ( "MQTT_ProcessLoop returned with status = %u.", + mqttStatus ) ); + } + } + else + { + sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + } } diff --git a/demos/ota/ota_demo_mqtt/CMakeLists.txt b/demos/ota/ota_demo_core_mqtt/CMakeLists.txt similarity index 95% rename from demos/ota/ota_demo_mqtt/CMakeLists.txt rename to demos/ota/ota_demo_core_mqtt/CMakeLists.txt index 404e411d9c..c01679d1d0 100644 --- a/demos/ota/ota_demo_mqtt/CMakeLists.txt +++ b/demos/ota/ota_demo_core_mqtt/CMakeLists.txt @@ -1,4 +1,4 @@ -set( DEMO_NAME "ota_demo_mqtt" ) +set( DEMO_NAME "ota_demo_core_mqtt" ) # Include required library's source and header path variables. include( ${CMAKE_SOURCE_DIR}/libraries/aws/ota/otaFilePaths.cmake ) @@ -13,7 +13,7 @@ find_library(LIB_RT rt REQUIRED) target_sources( ${DEMO_NAME} PRIVATE - "aws_iot_ota_update_demo.c" + "ota_demo_core_mqtt.c" ${OTA_SOURCES} ${OTA_OS_POSIX_SOURCES} ${OTA_MQTT_SOURCES} diff --git a/demos/ota/ota_demo_mqtt/aws_ota_agent_config.h b/demos/ota/ota_demo_core_mqtt/aws_ota_agent_config.h similarity index 100% rename from demos/ota/ota_demo_mqtt/aws_ota_agent_config.h rename to demos/ota/ota_demo_core_mqtt/aws_ota_agent_config.h diff --git a/demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h b/demos/ota/ota_demo_core_mqtt/aws_ota_codesigner_certificate.h similarity index 100% rename from demos/ota/ota_demo_mqtt/aws_ota_codesigner_certificate.h rename to demos/ota/ota_demo_core_mqtt/aws_ota_codesigner_certificate.h diff --git a/demos/ota/ota_demo_http/demo_config.h b/demos/ota/ota_demo_core_mqtt/demo_config.h similarity index 97% rename from demos/ota/ota_demo_http/demo_config.h rename to demos/ota/ota_demo_core_mqtt/demo_config.h index 5dd7926f58..a6dc6a9e9b 100644 --- a/demos/ota/ota_demo_http/demo_config.h +++ b/demos/ota/ota_demo_core_mqtt/demo_config.h @@ -83,7 +83,7 @@ * ROOT_CA_CERT_PATH to the absolute path if this demo is executed from elsewhere. */ #ifndef ROOT_CA_CERT_PATH - #define ROOT_CA_CERT_PATH "/home/ubuntu/dev/aws-iot-device-sdk-embedded-C-staging/demos/certificates/AmazonRootCA1.crt" + #define ROOT_CA_CERT_PATH "certificates/AmazonRootCA1.crt" #endif /** diff --git a/demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c b/demos/ota/ota_demo_core_mqtt/ota_demo_core_mqtt.c similarity index 98% rename from demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c rename to demos/ota/ota_demo_core_mqtt/ota_demo_core_mqtt.c index 47db704ede..9c66ba7762 100644 --- a/demos/ota/ota_demo_mqtt/aws_iot_ota_update_demo.c +++ b/demos/ota/ota_demo_core_mqtt/ota_demo_core_mqtt.c @@ -803,22 +803,20 @@ void startOTADemo( MQTTContext_t * pMqttContext ) OTA_GetPacketsProcessed(), OTA_GetPacketsDropped() ) ); - sleep( OTA_DEMO_TASK_DELAY_SECONDS ); - - // if(state == OtaAgentStateWaitingForJob ) - // { - // mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); - - // if( mqttStatus != MQTTSuccess ) - // { - // LogError( ( "MQTT_ProcessLoop returned with status = %u.", - // mqttStatus ) ); - // } - // } - // else - // { - // sleep( OTA_DEMO_TASK_DELAY_SECONDS ); - // } + if(state == OtaAgentStateWaitingForJob ) + { + mqttStatus = MQTT_ProcessLoop( pMqttContext, 1000 ); + + if( mqttStatus != MQTTSuccess ) + { + LogError( ( "MQTT_ProcessLoop returned with status = %u.", + mqttStatus ) ); + } + } + else + { + sleep( OTA_DEMO_TASK_DELAY_SECONDS ); + } }