ESP32产品系列之智能插座(二),ESP32代码部分

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、首页

该部分主要为博主本人学习记录,以便后续要用到的时候可以快速上手,同时也帮助初学者快速建立一个工程项目,学习MQTT通信;或者想要使用ESP32做开发的人,快速理解MQTT的运作方式的一个文章。因为博主本人代码功底有限,ESP32使用也不多,如有不对之处,请多包涵。

二、开发环境

ESP32的开发主要基于以下环境

  1. ESP32-WROOM-32D
  2. VSCODE
  3. esp-idf-v4.2

三、开发过程

基于esp-idf-v4.2的mqtt->tcp例程

  1. F1进入VSCODE控制台,输入ESP-IDF,选择展示示例项目
    在这里插入图片描述
  2. 选择MQTT的TCP例程,并保存到选定文件夹
    在这里插入图片描述
  3. 增加GPIO控制的头文件
#include "driver/gpio.h"
#include "sdkconfig.h"
  1. 在app_main()增加GPIO初始化代码

  2. 快捷键F1调出VSCODE控制台,输入ESP-IDF并选择SDK配置编辑器(menuconfig),设置连接的WIFI名字密码以及MQTT服务器地址。
    在这里插入图片描述
    Broker URL即服务器地址
    WIFI SSID即路由器的WIFI名字
    WIFI Password即WIFI密码

  3. 到了这一步基本上已经完成了配置的内容了,编译后的文件烧写进ESP32已经可以成功连接到服务器了,接下来要进行MQTT的特殊的信息处理方式了。
    MQTT主要靠主题来区分不同设备之间的不同信息的传输,设备只有订阅了一个主题,才能够收到来自该主题的消息,主题其实就是一串文字,可以理解为地址,类似于文件夹的地址。订阅主题是Subscribe,发布信息是Publish,取消订阅是Unsubscribe,再加上接收信息,这几个组成了MQTT的最底层状态机。

  4. 接下来修改订阅的主题。原本订阅的是”/topic/qos0“,需要修改到我们设计的主题,博主用的是”/test/1“,其余订阅其他主题的代码可以注释掉。
    在这里插入图片描述

  5. 主题订阅了之后,就可以处理来自于该主题的消息了,所以需要对信息进处理,并控制IO切换继电器。其中,MQTT_EVEN_DATA就是处理接受信息的状态机,因为代码少,所以直接就在状态机里面处理了。同时使用主题"/test/3"来上报处理结果。
    在这里插入图片描述

  6. 至此,已经完成了ESP32的MQTT通信以及控制继电器的代码移植修改,烧写到ESP32后就可以进行微信小程序部分的编写了

四、整体代码

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "mqtt_client.h"

#include "driver/gpio.h"
#include "sdkconfig.h"

#define BLINK_GPIO 32

static const char *TAG = "MQTT_EXAMPLE";


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, "/test/1", "data_3", 0, 1, 0);
            //ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

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

            //msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
           // ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

            //msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
            //ESP_LOGI(TAG, "sent unsubscribe 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, "/topic/qos0", "data", 0, 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);
            if(*event->data == 0x31)
            {
                msg_id = esp_mqtt_client_publish(client, "/test/3", "电源已开启", 0, 1, 0);
                gpio_set_level(BLINK_GPIO, 0);
            }
            else if(*event->data == 0x32)
            {
                msg_id = esp_mqtt_client_publish(client, "/test/3", "电源已关闭", 0, 1, 0);
                gpio_set_level(BLINK_GPIO, 1);
            }
            else
            {
                ESP_LOGI(TAG, "Data is unusable!");
            }            
            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_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .uri = CONFIG_BROKER_URL,
    };
#if CONFIG_BROKER_URL_FROM_STDIN
    char line[128];

    if (strcmp(mqtt_cfg.uri, "FROM_STDIN") == 0) {
        int count = 0;
        printf("Please enter url of mqtt broker\n");
        while (count < 128) {
            int c = fgetc(stdin);
            if (c == '\n') {
                line[count] = '\0';
                break;
            } else if (c > 0 && c < 127) {
                line[count] = c;
                ++count;
            }
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }
        mqtt_cfg.uri = line;
        printf("Broker url: %s\n", line);
    } else {
        ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
        abort();
    }
#endif /* CONFIG_BROKER_URL_FROM_STDIN */

    esp_mqtt_client_handle_t 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);
}


void app_main(void)
{
    gpio_pad_select_gpio(BLINK_GPIO);                   //初始化继电器控制IO

    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);   //设置IO为输出

    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());
    gpio_set_level(BLINK_GPIO, 1);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    printf("Turning on the LED\n");
    gpio_set_level(BLINK_GPIO, 0);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    printf("Turning off the LED\n");
    mqtt_app_start();
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的ESP8266智能插座程序示例,使用了Arduino IDE进行编写。该程序允许您通过手机应用程序或Web界面远程控制插座。 首先,您需要安装ESP8266板支持库和WiFiManager库。然后,将以下代码复制到Arduino IDE中,将您的WiFi SSID和密码添加到程序中,并上传到ESP8266开发板。 ```C++ #include <ESP8266WiFi.h> #include <WiFiManager.h> WiFiServer server(80); // 端口80用于Web服务器 String webPage = ""; // 存储Web页面的字符串 void setup() { // 初始化串行通信 Serial.begin(9600); // 连接到WiFi WiFiManager wifiManager; wifiManager.autoConnect("SmartSocket"); Serial.println("Connected to WiFi!"); // 启动Web服务器 server.begin(); Serial.println("Web server started!"); } void loop() { WiFiClient client = server.available(); if (client) { Serial.println("New client connected!"); while (client.connected()) { if (client.available()) { // 读取客户端请求 String request = client.readStringUntil('\r'); Serial.println(request); // 处理GET请求 if (request.indexOf("GET /") != -1) { // 生成Web页面 webPage = "<html><head><title>Smart Socket</title></head><body>"; webPage += "<h1>Smart Socket Control</h1>"; webPage += "<form method=\"get\" action=\"socket\"><button name=\"state\" value=\"on\">On</button><button name=\"state\" value=\"off\">Off</button></form>"; webPage += "</body></html>"; // 发送Web页面 client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.println(webPage); // 处理插座状态更改请求 } else if (request.indexOf("GET /socket") != -1) { // 读取状态更改请求 int stateStart = request.indexOf("state=") + 6; int stateEnd = request.indexOf("HTTP/") - 1; String state = request.substring(stateStart, stateEnd); // 更改插座状态 if (state == "on") { digitalWrite(5, LOW); // 打开插座 } else if (state == "off") { digitalWrite(5, HIGH); // 关闭插座 } // 生成确认页面 webPage = "<html><head><title>Smart Socket</title></head><body>"; webPage += "<h1>Smart Socket Control</h1>"; webPage += "<p>Socket turned " + state + "!</p>"; webPage += "</body></html>"; // 发送确认页面 client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.println(webPage); } } } // 断开客户端连接 client.stop(); Serial.println("Client disconnected!"); } } ``` 这个程序使用GPIO 5来控制插座的开关状态。在ESP8266上,GPIO 5对应于D1引脚。因此,您需要将插座的开关线连接到D1引脚和GND引脚。 上传完成后,打开串行监视器并重置ESP8266。它将连接到您的WiFi网络并显示其IP地址。将该IP地址输入到Web浏览器中,您将看到一个简单的Web页面,可用于控制插座的开关状态。 此外,您可以使用任何HTTP客户端(如Postman)来发送GET请求以更改插座状态。只需将以下URL添加到HTTP请求中:http://[ESP8266 IP地址]/socket?state=[on或off]。例如,要打开插座,可以使用以下URL:http://[ESP8266 IP地址]/socket?state=on。 希望这可以帮助您开始构建您自己的智能插座

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值