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连接阿里云

/*Broker Address:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com*/
#define   Aliyun_host       "iot-06z00f69gov61mh.mqtt.iothub.aliyuncs.com"
#define   Aliyun_port       1883
/*Client ID:     ${ClientID}|securemode=${Mode},signmethod=${SignMethod}|*/
#define   Aliyun_client_id  "ic3c6cpfq6I.esp32s3|securemode=2,signmethod=hmacsha256,timestamp=1691813578260|"
/*User Name:     ${DeviceName}&${ProductKey}*/
#define   Aliyun_username   "esp32s3&ic3c6cpfq6I"
/*使用官网 MQTT_Password 工具生成*/
#define   Aliyun_password   "18a216e310cf5c7337f04f8f0ea2243707b960007c6cd64e83e811f1a13af0e7"

#define   AliyunSubscribeTopic_user_get     "/ic3c6cpfq6I/esp32s3/user/get"
#define   AliyunPublishTopic_user_update    "/ic3c6cpfq6I/esp32s3/user/update"
#define   AliyunSubscribeTopic_post         "/sys/ic3c6cpfq6I/esp32s3/thing/event/property/post"
#define   AliyunSubscribeTopic_post_reply   "/sys/ic3c6cpfq6I/esp32s3/thing/event/property/post_reply"

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


char mqtt_message[256]={0};
char mqtt_publish_data1[] = "mqtt connect ok ";
char mqtt_publish_data2[] = "mqtt subscribe successful";
char mqtt_publish_data3[] = "mqtt i am esp32";

esp_mqtt_client_handle_t client;

static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int  msg_id;
	
    // your_context_t *context = event->context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data1, strlen(mqtt_publish_data1), 1, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

            msg_id = esp_mqtt_client_subscribe(client, AliyunSubscribeTopic_user_get, 0);
            ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

            break;
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            msg_id = esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data2, strlen(mqtt_publish_data2), 0, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
            printf("DATA=%.*s\r\n", event->data_len, event->data);
			
            break;
        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    mqtt_event_handler_cb(event_data);
}

static void mqtt_test_task(void *pvParameters)
{
    uint8_t num = 0;

    while(1)
    {
       esp_mqtt_client_publish(client, AliyunPublishTopic_user_update, mqtt_publish_data3, strlen(mqtt_publish_data3), 1, 0);
       vTaskDelay(2000 / portTICK_PERIOD_MS);
	   if(num++ > 2) break;
	}
    vTaskDelete(NULL);
}

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

void user_mqtt_app_start(void)
{

    esp_mqtt_client_config_t mqtt_cfg = {
		.host = Aliyun_host,
		.port = Aliyun_port,
		.client_id = Aliyun_client_id,
		.username = Aliyun_username,
		.password = Aliyun_password,

    };

     client = esp_mqtt_client_init(&mqtt_cfg);
     esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
     esp_mqtt_client_start(client);
     xTaskCreate(&mqtt_test_task, "mqtt_test_task", 4096, NULL, 5, NULL);
}

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

  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\"}",
          Temp,Humi,light,Soil, Bool, Rain);
       
          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


static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

void wifi_init_sta(void)
{

    s_wifi_event_group = xEventGroupCreate();

    /*Initialize the underlying TCP/IP stack. 
    NOTE:This function should be called exactly once from application code, when the application starts up. */
    ESP_ERROR_CHECK(esp_netif_init());

    /*Create default event loop. */
    ESP_ERROR_CHECK(esp_event_loop_create_default());

	/*Creates default WIFI STA. In case of any init error this API aborts. */
    esp_netif_create_default_wifi_sta();
 
    /*Init WiFi Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer, WiFi NVS structure etc, 
    this WiFi also start WiFi task. */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
	     .threshold.authmode = WIFI_AUTH_WPA2_PSK,

            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode( WIFI_MODE_APSTA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );

    ESP_LOGI(TAG, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_wifi_event_group);
    

}

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

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

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

void app_main(void)
{

    


    //Initialize NVS
    esp_err_t ret = nvs_flash_init();  
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
    //example_wifi_init();
    wifi_init_sta();
    user_mqtt_app_start();
    while(1)
    {
             
      vTaskDelay(200);
      
      break;
    }
	
}

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

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

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

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ESP32S3连接阿里云服务器可以使用ESP-IDF自带的MQTT客户端库,需要进行以下配置: 1. 在阿里云控制台创建一个MQTT实例,并获取到实例的Endpoint、Client ID、Username和Password。 2. 在ESP-IDF工程中,打开menuconfig界面,选择“Component Config” -> “ESP-MQTT” -> “MQTT Client Configuration”,进行如下配置: - MQTT Broker URI: 在此处输入阿里云MQTT实例的Endpoint,格式为“ssl://[Endpoint]:[Port]”,Port为1883或8883,如果使用SSL加密,需要选择8883端口。 - MQTT Client ID: 在此处输入阿里云MQTT实例的Client ID。 - MQTT Username: 在此处输入阿里云MQTT实例的Username。 - MQTT Password: 在此处输入阿里云MQTT实例的Password。 - MQTT Transport Type: 选择“MQTT_TRANSPORT_OVER_SSL”或“MQTT_TRANSPORT_OVER_TCP”,根据阿里云MQTT实例的协议类型选择。 3. 在代码中,使用esp_mqtt_client_init函数初始化MQTT客户端,并设置esp_mqtt_client_config_t结构体的相关参数,示例代码如下: ``` esp_mqtt_client_config_t mqtt_cfg = { .uri = "ssl://[Endpoint]:8883", .client_id = "[Client ID]", .username = "[Username]", .password = "[Password]", .transport = MQTT_TRANSPORT_OVER_SSL, //或MQTT_TRANSPORT_OVER_TCP }; esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_cfg); ``` 4. 在代码中,使用esp_mqtt_client_start函数启动MQTT客户端,示例代码如下: ``` esp_err_t err = esp_mqtt_client_start(mqtt_client); if (err != ESP_OK) { printf("MQTT client start failed: %s\n", esp_err_to_name(err)); } ``` 5. 在代码中,使用esp_mqtt_client_subscribe函数订阅MQTT主题,并使用esp_mqtt_client_publish函数发布MQTT消息,示例代码如下: ``` esp_mqtt_client_subscribe(mqtt_client, "/test/topic", 0); esp_mqtt_client_publish(mqtt_client, "/test/topic", "Hello, MQTT!", 0, 0, 0); ``` 以上就是ESP32S3连接阿里云服务器的MQTT客户端配置方法。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值