summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c')
-rw-r--r--FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c247
1 files changed, 208 insertions, 39 deletions
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c
index 6361b49b2..5b0f4e132 100644
--- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c
+++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/main.c
@@ -46,18 +46,80 @@ should an assert get hit. */
/* TCP/IP stack includes. */
#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+
+/* Demo app includes. */
+#include "demo_logging.h"
+
+/* Set the following constants to 1 or 0 to define which tasks to include and
+exclude:
+
+mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS: When set to 1 two UDP client tasks
+and two UDP server tasks are created. The clients talk to the servers. One set
+of tasks use the standard sockets interface, and the other the zero copy sockets
+interface. These tasks are self checking and will trigger a configASSERT() if
+they detect a difference in the data that is received from that which was sent.
+As these tasks use UDP, and can therefore loose packets, they will cause
+configASSERT() to be called when they are run in a less than perfect networking
+environment.
+
+mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS: TBD
+*/
+#define mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS 1
+#define mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS 0
+
+/* Simple UDP client and server task parameters. */
+#define mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY )
+#define mainSIMPLE_UDP_CLIENT_SERVER_PORT ( 5005UL )
/*
* Prototypes for the demos that can be started from this project.
*/
-extern void vStartSimpleTaskPoolDemo( void );
+extern void vStartSimpleMQTTDemo( void );
+extern void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulsPort, UBaseType_t uxPriority );
+
+/*
+ * Just seeds the simple pseudo random number generator.
+ *
+ * !!! NOTE !!!
+ * This is not a secure method of generating random numbers and production
+ * devices should use a true random number generator (TRNG).
+ */
+static void prvSRand( UBaseType_t ulSeed );
-/* This example is the first in a sequence that adds IoT functionality into
-an existing TCP/IP project. In this first project the TCP/IP stack is not
-actually used, but it is still built, which requires this array to be
-present. */
+/*
+ * Miscellaneous initialisation including preparing the logging and seeding the
+ * random number generator.
+ */
+static void prvMiscInitialisation( void );
+
+/* The default IP and MAC address used by the demo. The address configuration
+defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is
+1 but a DHCP server could not be contacted. See the online documentation for
+more information. */
+static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };
+static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };
+static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };
+static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };
+
+/* Set the following constant to pdTRUE to log using the method indicated by the
+name of the constant, or pdFALSE to not log using the method indicated by the
+name of the constant. Options include to standard out (xLogToStdout), to a disk
+file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE
+then UDP messages are sent to the IP address configured as the echo server
+address (see the configECHO_SERVER_ADDR0 definitions in FreeRTOSConfig.h) and
+the port number set by configPRINT_PORT in FreeRTOSConfig.h. */
+const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE;
+
+/* Default MAC address configuration. The demo creates a virtual network
+connection that uses this MAC address by accessing the raw Ethernet data
+to and from a real network connection on the host PC. See the
+configNETWORK_INTERFACE_TO_USE definition for information on how to configure
+the real network connection to use. */
const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };
+/* Use by the pseudo random number generator. */
+static UBaseType_t ulNextRand;
/*-----------------------------------------------------------*/
int main( void )
@@ -67,14 +129,20 @@ int main( void )
* TBD
*/
- /* Create the example that demonstrates task pool functionality. Examples
- that demonstrate networking connectivity will be added in future projects
- and get started after the network has connected (from within the
- vApplicationIPNetworkEventHook() function).*/
- vStartSimpleTaskPoolDemo();
+ /* Miscellaneous initialisation including preparing the logging and seeding
+ the random number generator. */
+ prvMiscInitialisation();
- /* Start the scheduler - if all is well from this point on only FreeRTOS
- tasks will execute. */
+ /* Initialise the network interface.
+
+ ***NOTE*** Tasks that use the network are created in the network event hook
+ when the network is connected and ready for use (see the implementation of
+ vApplicationIPNetworkEventHook() below). The address values passed in here
+ are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1
+ but a DHCP server cannot be contacted. */
+ FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
+
+ /* Start the RTOS scheduler. */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
@@ -118,46 +186,147 @@ volatile uint32_t ulLineNumber = ulLine;
events are only received if implemented in the MAC driver. */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
- /* This example is the first in a sequence that adds IoT functionality into
- an existing TCP/IP project. In this first project the TCP/IP stack is not
- actually used, but it is still built, which requires this function to be
- present. For now this function does not need to do anything, so just ensure
- the unused parameters don't cause compiler warnings and that calls to this
- function are trapped by the debugger. */
- __debugbreak();
- ( void ) eNetworkEvent;
+uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
+char cBuffer[ 16 ];
+static BaseType_t xTasksAlreadyCreated = pdFALSE;
+
+ /* If the network has just come up...*/
+ if( eNetworkEvent == eNetworkUp )
+ {
+ /* Create the tasks that use the IP stack if they have not already been
+ created. */
+ if( xTasksAlreadyCreated == pdFALSE )
+ {
+ #if( mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS == 1 )
+ {
+ vStartSimpleUDPClientServerTasks( configMINIMAL_STACK_SIZE, mainSIMPLE_UDP_CLIENT_SERVER_PORT, mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY );
+ }
+ #endif
+
+ #if( mainCREATE_SIMPLE_MQTT_EXAMPLE_TASKS == 1 )
+ {
+ vStartSimpleMQTTDemo();
+ }
+ #endif
+
+ xTasksAlreadyCreated = pdTRUE;
+ }
+
+ /* Print out the network configuration, which may have come from a DHCP
+ server. */
+ FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );
+ FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
+ FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );/*_RB_ Should use IoT libraries logging. */
+
+ FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
+ FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );
+
+ FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
+ FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );
+
+ FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
+ FreeRTOS_printf( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) );
+ }
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxRand( void )
+{
+const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
+
+ /*
+ * Utility function to generate a pseudo random number.
+ *
+ * !!!NOTE!!!
+ * This is not a secure method of generating a random number. Production
+ * devices should use a True Random Number Generator (TRNG).
+ */
+ ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
+ return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}
/*-----------------------------------------------------------*/
+static void prvSRand( UBaseType_t ulSeed )
+{
+ /* Utility function to seed the pseudo random number generator. */
+ ulNextRand = ulSeed;
+}
+/*-----------------------------------------------------------*/
+
+static void prvMiscInitialisation( void )
+{
+time_t xTimeNow;
+uint32_t ulLoggingIPAddress;
+
+ ulLoggingIPAddress = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR3 );
+ vLoggingInit( xLogToStdout, xLogToFile, xLogToUDP, ulLoggingIPAddress, configPRINT_PORT );
+
+ /* Seed the random number generator. */
+ time( &xTimeNow );
+ FreeRTOS_debug_printf( ( "Seed for randomiser: %lu\n", xTimeNow ) );
+ prvSRand( ( uint32_t ) xTimeNow );
+ FreeRTOS_debug_printf( ( "Random numbers: %08X %08X %08X %08X\n", ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32() ) );
+}
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
+
+ const char *pcApplicationHostnameHook( void )
+ {
+ /* Assign the name "FreeRTOS" to this network node. This function will
+ be called during the DHCP: the machine will be registered with an IP
+ address plus this name. */
+ return mainHOST_NAME;
+ }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#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( _stricmp( pcName, pcApplicationHostnameHook() ) == 0 )
+ {
+ xReturn = pdPASS;
+ }
+ else if( _stricmp( pcName, mainDEVICE_NICK_NAME ) == 0 )
+ {
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+ }
+
+#endif
+/*-----------------------------------------------------------*/
+
+/*
+ * Callback that provides the inputs necessary to generate a randomized TCP
+ * Initial Sequence Number per RFC 6528. THIS IS ONLY A DUMMY IMPLEMENTATION
+ * THAT RETURNS A PSEUDO RANDOM NUMBER SO IS NOT INTENDED FOR USE IN PRODUCTION
+ * SYSTEMS.
+ */
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort )
{
- /* This example is the first in a sequence that adds IoT functionality into
- an existing TCP/IP project. In this first project the TCP/IP stack is not
- actually used, but it is still built, which requires this function to be
- present. For now this function does not need to do anything, so just ensure
- the unused parameters don't cause compiler warnings and that calls to this
- function are trapped by the debugger. */
( void ) ulSourceAddress;
( void ) usSourcePort;
( void ) ulDestinationAddress;
( void ) usDestinationPort;
- __debugbreak();
- return 0;
-}
-/*-----------------------------------------------------------*/
-UBaseType_t uxRand( void )
-{
- /* This example is the first in a sequence that adds IoT functionality into
- an existing TCP/IP project. In this first project the TCP/IP stack is not
- actually used, but it is still built, which requires this function to be
- present. For now this function does not need to do anything, so just ensure
- the calls to the function are trapped by the debugger. */
- __debugbreak();
- return 0;
+ return uxRand();
}
/*-----------------------------------------------------------*/