• esp32s3通过mqtt协议连接阿里云(wifi+mqtt+vscode+espidf4.4.4+py3.8.7)


    1.MQTT协议

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。

    MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务

    作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

    MQTT协议特点

    MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。

    MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。

    简单介绍一下MQTT协议,关于具体的报文读者可以自行了解,本文在于应用。

    2.MQTT连接阿里云

    1. /*Broker Address:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com*/
    2. #define Aliyun_host "iot-06z00f69gov61mh.mqtt.iothub.aliyuncs.com"
    3. #define Aliyun_port 1883
    4. /*Client ID: ${ClientID}|securemode=${Mode},signmethod=${SignMethod}|*/
    5. #define Aliyun_client_id "ic3c6cpfq6I.esp32s3|securemode=2,signmethod=hmacsha256,timestamp=1691813578260|"
    6. /*User Name: ${DeviceName}&${ProductKey}*/
    7. #define Aliyun_username "esp32s3&ic3c6cpfq6I"
    8. /*使用官网 MQTT_Password 工具生成*/
    9. #define Aliyun_password "18a216e310cf5c7337f04f8f0ea2243707b960007c6cd64e83e811f1a13af0e7"
    10. #define AliyunSubscribeTopic_user_get "/ic3c6cpfq6I/esp32s3/user/get"
    11. #define AliyunPublishTopic_user_update "/ic3c6cpfq6I/esp32s3/user/update"
    12. #define AliyunSubscribeTopic_post "/sys/ic3c6cpfq6I/esp32s3/thing/event/property/post"
    13. #define AliyunSubscribeTopic_post_reply "/sys/ic3c6cpfq6I/esp32s3/thing/event/property/post_reply"

    这是MQTT连接参数,我们可以去阿里云中的物联网平台中的产品参数中找到。

    1. char mqtt_message[256]={0};
    2. char mqtt_publish_data1[] = "mqtt connect ok ";
    3. char mqtt_publish_data2[] = "mqtt subscribe successful";
    4. char mqtt_publish_data3[] = "mqtt i am esp32";
    5. esp_mqtt_client_handle_t client;
    6. static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
    7. {
    8. esp_mqtt_client_handle_t client = event->client;
    9. int msg_id;
    10. // your_context_t *context = event->context;
    11. switch (event->event_id) {
    12. case MQTT_EVENT_CONNECTED:
    13. ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
    14. msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data1, strlen(mqtt_publish_data1), 1, 0);
    15. ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
    16. msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0);
    17. ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
    18. break;
    19. case MQTT_EVENT_DISCONNECTED:
    20. ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
    21. break;
    22. case MQTT_EVENT_SUBSCRIBED:
    23. ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
    24. msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data2, strlen(mqtt_publish_data2), 0, 0);
    25. ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
    26. break;
    27. case MQTT_EVENT_UNSUBSCRIBED:
    28. ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
    29. break;
    30. case MQTT_EVENT_PUBLISHED:
    31. ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
    32. break;
    33. case MQTT_EVENT_DATA:
    34. ESP_LOGI(TAG, "MQTT_EVENT_DATA");
    35. printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
    36. printf("DATA=%.*s\r\n", event->data_len, event->data);
    37. break;
    38. case MQTT_EVENT_ERROR:
    39. ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
    40. break;
    41. default:
    42. ESP_LOGI(TAG, "Other event id:%d", event->event_id);
    43. break;
    44. }
    45. return ESP_OK;
    46. }
    47. static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    48. ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    49. mqtt_event_handler_cb(event_data);
    50. }
    51. static void mqtt_test_task(void *pvParameters)
    52. {
    53. uint8_t num = 0;
    54. while(1)
    55. {
    56. esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data3, strlen(mqtt_publish_data3), 1, 0);
    57. vTaskDelay(2000 / portTICK_PERIOD_MS);
    58. if(num++ > 2) break;
    59. }
    60. vTaskDelete(NULL);
    61. }

    这是连云的相关函数,我们通过espidf中的日志打印出我们执行的操作。同样的创建一个线程来进行连云。

    1. void user_mqtt_app_start(void)
    2. {
    3. esp_mqtt_client_config_t mqtt_cfg = {
    4. .host = Aliyun_host,
    5. .port = Aliyun_port,
    6. .client_id = Aliyun_client_id,
    7. .username = Aliyun_username,
    8. .password = Aliyun_password,
    9. };
    10. client = esp_mqtt_client_init(&mqtt_cfg);
    11. esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    12. esp_mqtt_client_start(client);
    13. xTaskCreate(&mqtt_test_task, "mqtt_test_task", 4096, NULL, 5, NULL);
    14. }

    这是我们在mqtt.c里面的头文件,创建一个客户端,通过mqtt参数连接至阿里云。

    1. sprintf(mqtt_message,"{\"method\":\"thing.event.property.post\",\"params\":{\"temperature\":%d,\"Humidity\":%d,\"LightLux\":%d,\"soilHumidity\":%d,\"WaterOutletSwitch\":%d,\"Rain\":%d,},\"version\":\"1.1.1\"}",
    2. Temp,Humi,light,Soil, Bool, Rain);
    3. esp_mqtt_client_publish(client, AliyunSubscribeTopic_post, mqtt_message, strlen(mqtt_message), 0, 0);//上传

     这是我们的数据上传代码,我们通过#include "mqtt_client.h"这个头文件中的函数,将我们要上传的数据通过sprintf这个函数形成一个字符串,然后通过esp_mqtt_client_publish把数据上传至阿里云。

    3.设置WIFI

    1. static void event_handler(void* arg, esp_event_base_t event_base,
    2. int32_t event_id, void* event_data)
    3. {
    4. if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
    5. esp_wifi_connect();
    6. } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
    7. if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
    8. esp_wifi_connect();
    9. s_retry_num++;
    10. ESP_LOGI(TAG, "retry to connect to the AP");
    11. } else {
    12. xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
    13. }
    14. ESP_LOGI(TAG,"connect to the AP fail");
    15. } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
    16. ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
    17. ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
    18. s_retry_num = 0;
    19. xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    20. }
    21. }
    22. void wifi_init_sta(void)
    23. {
    24. s_wifi_event_group = xEventGroupCreate();
    25. /*Initialize the underlying TCP/IP stack.
    26. NOTE:This function should be called exactly once from application code, when the application starts up. */
    27. ESP_ERROR_CHECK(esp_netif_init());
    28. /*Create default event loop. */
    29. ESP_ERROR_CHECK(esp_event_loop_create_default());
    30. /*Creates default WIFI STA. In case of any init error this API aborts. */
    31. esp_netif_create_default_wifi_sta();
    32. /*Init WiFi Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, WiFi NVS structure etc,
    33. this WiFi also start WiFi task. */
    34. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    35. ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    36. esp_event_handler_instance_t instance_any_id;
    37. esp_event_handler_instance_t instance_got_ip;
    38. ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
    39. ESP_EVENT_ANY_ID,
    40. &event_handler,
    41. NULL,
    42. &instance_any_id));
    43. ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
    44. IP_EVENT_STA_GOT_IP,
    45. &event_handler,
    46. NULL,
    47. &instance_got_ip));
    48. wifi_config_t wifi_config = {
    49. .sta = {
    50. .ssid = EXAMPLE_ESP_WIFI_SSID,
    51. .password = EXAMPLE_ESP_WIFI_PASS,
    52. /* Setting a password implies station will connect to all security modes including WEP/WPA.
    53. * However these modes are deprecated and not advisable to be used. Incase your Access point
    54. * doesn't support WPA2, these mode can be enabled by commenting below line */
    55. .threshold.authmode = WIFI_AUTH_WPA2_PSK,
    56. .pmf_cfg = {
    57. .capable = true,
    58. .required = false
    59. },
    60. },
    61. };
    62. ESP_ERROR_CHECK(esp_wifi_set_mode( WIFI_MODE_APSTA) );
    63. ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    64. ESP_ERROR_CHECK(esp_wifi_start() );
    65. ESP_LOGI(TAG, "wifi_init_sta finished.");
    66. /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
    67. * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    68. EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
    69. WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
    70. pdFALSE,
    71. pdFALSE,
    72. portMAX_DELAY);
    73. /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
    74. * happened. */
    75. if (bits & WIFI_CONNECTED_BIT) {
    76. ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
    77. EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    78. } else if (bits & WIFI_FAIL_BIT) {
    79. ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
    80. EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    81. } else {
    82. ESP_LOGE(TAG, "UNEXPECTED EVENT");
    83. }
    84. /* The event will not be processed after unregister */
    85. ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    86. ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    87. vEventGroupDelete(s_wifi_event_group);
    88. }

    我们首先创建一个事件处理函数,但我们没用连接上wifi时,便会在控制台日志一直打印AP fail。

    下面的就是我们把esp32s3设置成sta模式,连接WiFi,然后打印出ip地址。

    注意:我们单片机连接的WiFi最好都设置成2.4G频段的,不然可能会连接不上或者不稳定。

    1. void app_main(void)
    2. {
    3. //Initialize NVS
    4. esp_err_t ret = nvs_flash_init();
    5. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    6. ESP_ERROR_CHECK(nvs_flash_erase());
    7. ret = nvs_flash_init();
    8. }
    9. ESP_ERROR_CHECK(ret);
    10. ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
    11. //example_wifi_init();
    12. wifi_init_sta();
    13. user_mqtt_app_start();
    14. while(1)
    15. {
    16. vTaskDelay(200);
    17. break;
    18. }
    19. }

    这样我们便可以通过esp32s3自带的wifi模块连接wifi并将数据发送至阿里云平台。

    具体代码在我资源里,大家可以下载参考。

    我的开发环境是VScode+espidf4.4.4+python3.8.7.

  • 相关阅读:
    ts声明文件
    Vue3生命周期
    深入解析Linux Bridge:原理、架构、操作与持久化配置
    5个免费 UI、界面设计素材网
    EMC测试项目
    华为hwics格式产品文档打开方式
    linux下centos7升级python版本
    LeetCode 356. Line Reflection【数学,哈希表】中等
    C++算法之旅、04 基础篇 | 第一章 基础算法
    最热门的跨考考研5大专业是哪些?
  • 原文地址:https://blog.csdn.net/ljt2333/article/details/133214557