/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "lwip.h" #include #include "wolfmqtt/mqtt_client.h" #include"wolfmqtt/mqtt_packet.h" #include"wolfmqtt/mqtt_socket.h" #include"wolfmqtt/mqtt_types.h" #include "wolfSSL.I-CUBE-wolfMQTT_conf.h" #include"wolfmqtt/userio_template.h" //#include"mqttexample.h" #define MQTT_HOST "test.mosquitto.org" #define MQTT_QOS MQTT_QOS_0 #define MQTT_KEEP_ALIVE_SEC 60 #define MQTT_CMD_TIMEOUT_MS 30000 #define MQTT_CON_TIMEOUT_MS 5000 #define MQTT_CLIENT_ID "WolfMQTTClientSimple" #define MQTT_TOPIC_NAME "wolfMQTT/example/testTopic" #define MQTT_PUBLISH_MSG "Test Publish" #define MQTT_USERNAME NULL #define MQTT_PASSWORD NULL #define MQTT_USE_TLS 1 #define MQTT_MAX_PACKET_SZ 1024 #define INVALID_SOCKET_FD -1 #define PRINT_BUFFER_SIZE 80 #define MQTT_PORT 1883 /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ MqttObject mqttobject; static MqttClient mClient; static MqttNet mNetwork; static int mSockFd = INVALID_SOCKET_FD; static byte mSendBuf[MQTT_MAX_PACKET_SZ]; static byte mReadBuf[MQTT_MAX_PACKET_SZ]; static volatile word16 mPacketIdLast; /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_LWIP_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ // MqttClient_Publish(&mqttCtx->client, &mqttCtx->publish); // MqttClient_Publish(&client,0,'vishal',0,15,20); // MqttClient_Publish(&client, ); XMEMSET((&mqttobject), (0), (sizeof(mqttobject))); /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ MX_LWIP_Process(); // mqttsimple_test(); // MqttClient_Init(); // MqttClient_NetConnect(); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 13; RCC_OscInitStruct.PLL.PLLN = 195; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 5; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { Error_Handler(); } } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ static int mqtt_message_cb(MqttClient *client, MqttMessage *msg, byte msg_new, byte msg_done) { byte buf[PRINT_BUFFER_SIZE+1]; word32 len; (void)client; if (msg_new) { /* Determine min size to dump */ len = msg->topic_name_len; if (len > PRINT_BUFFER_SIZE) { len = PRINT_BUFFER_SIZE; } XMEMCPY(buf, msg->topic_name, len); buf[len] = '\0'; /* Make sure its null terminated */ /* Print incoming message */ PRINTF("MQTT Message: Topic %s, Qos %d, Len %u", buf, msg->qos, msg->total_len); } /* Print message payload */ len = msg->buffer_len; if (len > PRINT_BUFFER_SIZE) { len = PRINT_BUFFER_SIZE; } XMEMCPY(buf, msg->buffer, len); buf[len] = '\0'; /* Make sure its null terminated */ PRINTF("Payload (%d - %d) printing %d bytes:" LINE_END "%s", msg->buffer_pos, msg->buffer_pos + msg->buffer_len, len, buf); if (msg_done) { PRINTF("MQTT Message: Done"); } /* Return negative to terminate publish processing */ return MQTT_CODE_SUCCESS; } static void setup_timeout(struct timeval* tv, int timeout_ms) { tv->tv_sec = timeout_ms / 1000; tv->tv_usec = (timeout_ms % 1000) * 1000; /* Make sure there is a minimum value specified */ if (tv->tv_sec < 0 || (tv->tv_sec == 0 && tv->tv_usec <= 0)) { tv->tv_sec = 0; tv->tv_usec = 100; } } static int socket_get_error(int sockFd) { int so_error = 0; socklen_t len = sizeof(so_error); getsockopt(sockFd, SOL_SOCKET, SO_ERROR, &so_error, &len); return so_error; } static int mqtt_net_connect(void *context, const char* host, word16 port, int timeout_ms) { int rc; int sockFd, *pSockFd = (int*)context; struct sockaddr_in addr; struct addrinfo *result = NULL; struct addrinfo hints; if (pSockFd == NULL) { return MQTT_CODE_ERROR_BAD_ARG; } (void)timeout_ms; /* get address */ XMEMSET(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; XMEMSET(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; rc = getaddrinfo(host, NULL, &hints, &result); if (rc >= 0 && result != NULL) { struct addrinfo* res = result; /* prefer ip4 addresses */ while (res) { if (res->ai_family == AF_INET) { result = res; break; } res = res->ai_next; } if (result->ai_family == AF_INET) { addr.sin_port = htons(port); addr.sin_family = AF_INET; addr.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr; } else { rc = -1; } freeaddrinfo(result); } if (rc < 0) { return MQTT_CODE_ERROR_NETWORK; } sockFd = socket(addr.sin_family, SOCK_STREAM, 0); if (sockFd < 0) { return MQTT_CODE_ERROR_NETWORK; } /* Start connect */ rc = connect(sockFd, (struct sockaddr*)&addr, sizeof(addr)); if (rc < 0) { PRINTF("NetConnect: Error %d (Sock Err %d)", rc, socket_get_error(*pSockFd)); close(sockFd); return MQTT_CODE_ERROR_NETWORK; } /* save socket number to context */ *pSockFd = sockFd; return MQTT_CODE_SUCCESS; } static int mqtt_net_read(void *context, byte* buf, int buf_len, int timeout_ms) { int rc; int *pSockFd = (int*)context; int bytes = 0; struct timeval tv; if (pSockFd == NULL) { return MQTT_CODE_ERROR_BAD_ARG; } /* Setup timeout */ setup_timeout(&tv, timeout_ms); setsockopt(*pSockFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); /* Loop until buf_len has been read, error or timeout */ while (bytes < buf_len) { rc = (int)recv(*pSockFd, &buf[bytes], buf_len - bytes, 0); if (rc < 0) { rc = socket_get_error(*pSockFd); if (rc == 0) break; /* timeout */ PRINTF("NetRead: Error %d", rc); return MQTT_CODE_ERROR_NETWORK; } bytes += rc; /* Data */ } if (bytes == 0) { return MQTT_CODE_ERROR_TIMEOUT; } return bytes; } static int mqtt_net_write(void *context, const byte* buf, int buf_len, int timeout_ms) { int rc; int *pSockFd = (int*)context; struct timeval tv; if (pSockFd == NULL) { return MQTT_CODE_ERROR_BAD_ARG; } /* Setup timeout */ setup_timeout(&tv, timeout_ms); setsockopt(*pSockFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); rc = (int)send(*pSockFd, buf, buf_len, 0); if (rc < 0) { PRINTF("NetWrite: Error %d (Sock Err %d)", rc, socket_get_error(*pSockFd)); return MQTT_CODE_ERROR_NETWORK; } return rc; } static int mqtt_net_disconnect(void *context) { int *pSockFd = (int*)context; if (pSockFd == NULL) { return MQTT_CODE_ERROR_BAD_ARG; } close(*pSockFd); *pSockFd = INVALID_SOCKET_FD; return MQTT_CODE_SUCCESS; } #ifdef ENABLE_MQTT_TLS static int mqtt_tls_verify_cb(int preverify, WOLFSSL_X509_STORE_CTX* store) { char buffer[WOLFSSL_MAX_ERROR_SZ]; PRINTF("MQTT TLS Verify Callback: PreVerify %d, Error %d (%s)", preverify, store->error, store->error != 0 ? wolfSSL_ERR_error_string(store->error, buffer) : "none"); PRINTF(" Subject's domain name is %s", store->domain); if (store->error != 0) { /* Allowing to continue */ /* Should check certificate and return 0 if not okay */ PRINTF(" Allowing cert anyways"); } return 1; } /* Use this callback to setup TLS certificates and verify callbacks */ static int mqtt_tls_cb(MqttClient* client) { int rc = WOLFSSL_FAILURE; /* Use highest available and allow downgrade. If wolfSSL is built with * old TLS support, it is possible for a server to force a downgrade to * an insecure version. */ client->tls.ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (client->tls.ctx) { wolfSSL_CTX_set_verify(client->tls.ctx, WOLFSSL_VERIFY_PEER, mqtt_tls_verify_cb); /* default to success */ rc = WOLFSSL_SUCCESS; #if !defined(NO_CERT) #if 0 /* Load CA certificate buffer */ rc = wolfSSL_CTX_load_verify_buffer(client->tls.ctx, caCertBuf, caCertSize, WOLFSSL_FILETYPE_PEM); #endif #if 0 /* If using a client certificate it can be loaded using: */ rc = wolfSSL_CTX_use_certificate_buffer(client->tls.ctx, clientCertBuf, clientCertSize, WOLFSSL_FILETYPE_PEM); #endif #endif /* !NO_CERT */ } PRINTF("MQTT TLS Setup (%d)", rc); return rc; } #else static int mqtt_tls_cb(MqttClient* client) { (void)client; return 0; } #endif /* ENABLE_MQTT_TLS */ static word16 mqtt_get_packetid(void) { /* Check rollover */ if (mPacketIdLast >= MAX_PACKET_ID) { mPacketIdLast = 0; } return ++mPacketIdLast; } int mqttsimple_test(void) { int rc = 0; MqttObject mqttObj; MqttTopic topics[1]; /* Initialize MQTT client */ XMEMSET(&mNetwork, 0, sizeof(mNetwork)); mNetwork.connect = mqtt_net_connect; mNetwork.read = mqtt_net_read; mNetwork.write = mqtt_net_write; mNetwork.disconnect = mqtt_net_disconnect; mNetwork.context = &mSockFd; rc = MqttClient_Init(&mClient, &mNetwork, mqtt_message_cb, mSendBuf, sizeof(mSendBuf), mReadBuf, sizeof(mReadBuf), MQTT_CON_TIMEOUT_MS); if (rc != MQTT_CODE_SUCCESS) { goto exit; } PRINTF("MQTT Init Success"); /* Connect to broker */ rc = MqttClient_NetConnect(&mClient, MQTT_HOST, MQTT_PORT, MQTT_CON_TIMEOUT_MS, MQTT_USE_TLS, mqtt_tls_cb); if (rc != MQTT_CODE_SUCCESS) { goto exit; } PRINTF("MQTT Network Connect Success: Host %s, Port %d, UseTLS %d", MQTT_HOST, MQTT_PORT, MQTT_USE_TLS); /* Send Connect and wait for Ack */ XMEMSET(&mqttObj, 0, sizeof(mqttObj)); mqttObj.connect.keep_alive_sec = MQTT_KEEP_ALIVE_SEC; mqttObj.connect.client_id = MQTT_CLIENT_ID; mqttObj.connect.username = MQTT_USERNAME; mqttObj.connect.password = MQTT_PASSWORD; rc = MqttClient_Connect(&mClient, &mqttObj.connect); if (rc != MQTT_CODE_SUCCESS) { goto exit; } PRINTF("MQTT Broker Connect Success: ClientID %s, Username %s, Password %s", MQTT_CLIENT_ID, (MQTT_USERNAME == NULL) ? "Null" : MQTT_USERNAME, (MQTT_PASSWORD == NULL) ? "Null" : MQTT_PASSWORD); /* Subscribe and wait for Ack */ XMEMSET(&mqttObj, 0, sizeof(mqttObj)); topics[0].topic_filter = MQTT_TOPIC_NAME; topics[0].qos = MQTT_QOS; mqttObj.subscribe.packet_id = mqtt_get_packetid(); mqttObj.subscribe.topic_count = sizeof(topics) / sizeof(MqttTopic); mqttObj.subscribe.topics = topics; rc = MqttClient_Subscribe(&mClient, &mqttObj.subscribe); if (rc != MQTT_CODE_SUCCESS) { goto exit; } PRINTF("MQTT Subscribe Success: Topic %s, QoS %d", MQTT_TOPIC_NAME, MQTT_QOS); /* Publish */ XMEMSET(&mqttObj, 0, sizeof(mqttObj)); mqttObj.publish.qos = MQTT_QOS; mqttObj.publish.topic_name = MQTT_TOPIC_NAME; mqttObj.publish.packet_id = mqtt_get_packetid(); mqttObj.publish.buffer = (byte*)MQTT_PUBLISH_MSG; mqttObj.publish.total_len = XSTRLEN(MQTT_PUBLISH_MSG); rc = MqttClient_Publish(&mClient, &mqttObj.publish); if (rc != MQTT_CODE_SUCCESS) { goto exit; } PRINTF("MQTT Publish: Topic %s, Qos %d, Message %s", mqttObj.publish.topic_name, mqttObj.publish.qos, mqttObj.publish.buffer); /* Wait for messages */ while (1) { rc = MqttClient_WaitMessage_ex(&mClient, &mqttObj, MQTT_CMD_TIMEOUT_MS); if (rc == MQTT_CODE_ERROR_TIMEOUT) { /* send keep-alive ping */ rc = MqttClient_Ping_ex(&mClient, &mqttObj.ping); if (rc != MQTT_CODE_SUCCESS) { break; } PRINTF("MQTT Keep-Alive Ping"); } else if (rc != MQTT_CODE_SUCCESS) { break; } } if (rc != MQTT_CODE_SUCCESS) { PRINTF("MQTT Error %d: %s", rc, MqttClient_ReturnCodeToString(rc)); } return rc; }