ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)

ESP32-C3学到现在,我们已经掌握了从基本外设到网络服务端的相关知识,
这篇文章就是做一个简单的应用,使用开发板连接ONENET云平台,
使用MQTT协议,上报温湿度和光照数据,平台下发命令控制全彩灯颜色切换。

目录

  • 前言
  • 一、整体框架设计
    • 1.1 配网添加(Smart_config )
    • 1.2 周期上报数据(Timer)
    • 1.3 光照度采集(ADC)
    • 1.4 温湿度采集(I2C)
    • 1.5 按键(GPIO)
  • 二、ONENET平台设置
    • 2.1 添加产品 和设备
    • 2.2 为设备添加数据流
    • 2.3 云平台协议参数说明
      • 2.3.1 ONENET MQTT服务器地址
      • 2.3.2 clientld、username、password
      • 2.3.3 password 获取方法
    • 2.4 订阅Topic
    • 2.5 发送数据至云平台
    • 2.6 云平台下发命令
  • 三、整体调整测试
    • 3.1 结合平台的基本调整
    • 3.2 .url 和 .host
    • 3.3 周期上报效果
    • 3.4 下行命令处理(RMT应用)
  • 附录(源码)

前言

接下来的 ESP32-C3 功能测试都是基于自己设计的开发板:

自己画一块ESP32-C3 的开发板(第一次使用立创EDA)(PCB到手)

开发环境是乐鑫官方的 ESP-IDF, 基于VScode插件搭建好的:

ESP32-C3 VScode开发环境搭建(基于乐鑫官方ESP-IDF——Windows和Ubuntu双环境)

本文作为一个具体的应用实现,把前面博文所学的知识做了个结合,具体实现的功能如下:

1. 光照度采集
ESP32-C3入门教程 基础篇(一、ADC采样)

2. 温湿度采集
ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)

3.按键操作
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试)

4.全彩RGB LED控制
ESP32-C3入门教程 基础篇(五、RMT应用 — SK6812全彩RGB LED灯驱动测试)

5.周期上报数据
ESP32-C3入门教程 基础篇(六、TIMG 硬件定时器 与 软件定时器)

6.WiFi配网
ESP32-C3入门教程 网络 篇(一、 Wi-Fi 使用入门 — 初始化及STA、AP模式)
ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)

7.MQTT连接云平台
ESP32-C3入门教程 网络 篇(三、 MQTT 协议基础介绍及测试)

我们还没有讲解 ESP-IDF 的工程结构,本文虽然是综合应用实例,目的在于实现一个完成的小项目实例,对于工程代码文件结构,规范性没有处理,示例是以简单的形式呈现,特此申明! 勿杠!

当初计划是使用阿里云,但是我想到自己的手机阿里云还是新用户,新用户会有采购优惠,不能浪费了= =, 所以为了优惠这里抛弃了阿里云,采用OneNet。

一、整体框架设计

首先明白,本实例的核心部分就是 MQTT 的通信,所以整体的框架是基于 MQTT 的Demo 进行修改,
在以此为基本框架的基础上增加我们需要的组件,功能,函数。

1.1 配网添加(Smart_config )

删除 MQTT Demo中关于配网的操作,使用 Smart_config 配网方式,直接拷贝 Smart_config Demo中的函数:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第1张图片
Smart_Config的初始化函数,回调函数,任务函数都直接复制Smart_config Demo中的即可,但是得注意 其中的任务smartconfig_example_task 配网结束后需要删除,节约空间,如下图:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第2张图片

1.2 周期上报数据(Timer)

周期上报数据使用硬件定时器方式,使能一个 自动重装载的定时器,在定时器中断函数中改变状态位,提醒需要上报数据,需要的代码比定时器 demo 中的简单,只需要需要的功能,如下:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第3张图片

1.3 光照度采集(ADC)

光照度采集使用的事ADC采样,只需要简单的在 主函数中使能了ADC,直接采用单次采样的方式,加上一下数据处理,结合上面的定时器,就能实现一个周期上报功能:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第4张图片

测试效果:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第5张图片

1.4 温湿度采集(I2C)

温湿度的采集,还是根据 ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)中的内容,添加对应的 sht21.c 和 sht21.h 文件,然后在周期任务处调用测试:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第6张图片
测试效果:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第7张图片

1.5 按键(GPIO)

按键操作目的在于,当产品需要配网的时候,手动删除以前的配网信息,按键的操作在
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试) 有过说明,同时在 ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)也有过说明,这里主要的用法和Wi-Fi配网教学篇中的一样,按键会主动删除曾经有过的配网信息,导致产品重新进入配网:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第8张图片
测试效果:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第9张图片
重启以后重新配网能够回归正常。

完成程序的框架设计搭建,接下来就要进场云平台的产品创建。

二、ONENET平台设置

在 OneNET平台,进入控制台,找到对应的MQTT 物联网套件:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第10张图片

2.1 添加产品 和设备

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第11张图片

产品添加成功,此时可以点击如下图片立即添加设备:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第12张图片

如果当时没有立即添加,可以在产品概况的(左边栏目),设备列表里面找到关于设备的相关信息,进行添加设备:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第13张图片

添加完成后,可以看到设备离线,然后一些基本信息:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第14张图片

2.2 为设备添加数据流

找到设备
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第15张图片

2.3 云平台协议参数说明

前面完成了云平台的设置,我们可以通过PC客户端先对云平台进行一个测试,在这之前,需要先了解一下ONENET MQTT协议规范的基本介绍,通过如下网站可以查找到所有需要的ONENET MQTT介绍:

OneNET MQTT 协议规范文档说明
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第16张图片

2.3.1 ONENET MQTT服务器地址

mqtts.heclouds.com 	 1883

OneNET MQTT 服务器地址

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第17张图片

2.3.2 clientld、username、password

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第18张图片
更加详细的介绍如下图:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第19张图片

2.3.3 password 获取方法

连接除了clientld、username,还需要password 。 ONENET的 password 需要使用费 token 算法 获取:

ONENET token 算法说明
ONENET token工具下载
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第20张图片
1、products/产品ID/devices/设备名称
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第21张图片
2、时间戳

通过这个的工具获取: 在线 时间戳转换工具

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第22张图片
填入工具之中:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第23张图片
3、key
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第24张图片
4、生成密码
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第25张图片

通过 MQTT.fx 配置连接云平台,按照如下配置进行设置:

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第26张图片

配置完成以后,点击connect,在ONENET上可以看到设备在线状态:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第27张图片

2.4 订阅Topic

ONENET平台 与设备 Topic 的约定,不能随意的定义自己的Topic,有对应的规定:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第28张图片
有如下一些Topic:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第29张图片
比如,我们订阅一个上报结果,类似如图所示:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第30张图片

2.5 发送数据至云平台

我们上面完成了数据上报结果订阅,那么有关于任何数据点上报的结果,我们都能收到消息,我们使用工具来尝试一下给平台发送数据:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第31张图片
在 MQTT.fx 中,数据格式使用 Json 格式发送:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第32张图片

点击发布,我们可以通过订阅的消息看到消息已经发送,在云平台也能看到数据上报成功:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第33张图片

2.6 云平台下发命令

接收平台下发的命令,就是订阅设备所有命令相关消息:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第34张图片

在云平台点击下发命令,如下图,然后写入cmd,在MQTT.fx 中我们订阅过消息,所以能够收到命令:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第35张图片
测试完成,到时候我们将会使用这个命令来控制板子上的RGB灯。

三、整体调整测试

3.1 结合平台的基本调整

在前面其实有提到过 topic 的说明,设备发布消息到非法topic ,平台会断开设备连接:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第36张图片

所以在整体修改的过程中需要注意,不要有其他的无用的测试Topic 。

在前面修改完成的整体程序框架中,根据平台的测试结果,修改一些必要的地方:

一些基本的定义:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第37张图片MQTT配置部分代码:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第38张图片
周期上报的逻辑:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第39张图片

3.2 .url 和 .host

在此期间测试有一个问题:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第40张图片
实际上这里有个概念没有搞清楚:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第41张图片

此处的内容可参考博文:网址(url),域名,ip地址,dns,hosts之间的关系

3.3 周期上报效果

最终测试结果,周期上报板子上传感器数值,在云平台可以看到周期上报的结果:

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第42张图片
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第43张图片

3.4 下行命令处理(RMT应用)

下行命令处理,我们这里是基于订阅了云平台的 CMD 命令,但是对于这个下行的命令,目前看到也并没有一个标准的格式指定。这里目的是为了演示,所以我们怎么简单怎么来。
我们自己把下行需要处理的命令格式定位: mycmd:XXXXX。
比如:mycmd:ledred mycmd:ledblue。
这样,我们通过接受到的消息经常简单的数据处理以后,做出对应的动作。
(具体的执行可参考源码)
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第44张图片

测试结果, 切换成蓝灯:

ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第45张图片

测试结果,切换成红灯:
ESP32-C3入门教程 应用 篇(实例一、通过MQTT协议连接 ONENET 平台)_第46张图片

附录(源码)

这里上一下app_main.c文件源码,其实只要看过我的教学博文,下面这个文件的代码都是有分析说明的,包括本文上面也对每个部分的功能有单独说明。整个应用工程的代码,我上传到了资源:

本博文工程源码

app_main.c

/* MQTT (over TCP) Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include 
#include 
#include 
#include 
#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"
/*
smartconfig
*/
#include "esp_smartconfig.h"   
#include "freertos/event_groups.h"
// #include "esp_wpa2.h"
/*
定时器
*/
#include "driver/timer.h" 
/*
ADC
*/
#include "driver/adc.h"
#include "driver/gpio.h" 
/*
I2C
*/  
#include "sht21.h"
/*
button
*/
#include "my_button.h"
/*
RMT
*/
#include "driver/rmt.h"
#include "led_strip.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"

#define TIMER_SCALE           (TIMER_BASE_CLK / 16)  // convert counter value to seconds


#define ONENET_MqttServer "mqtts.heclouds.com"

#define ONENET_clientld   "esp32-device1"  //name
#define ONENET_UserName   "493136"     //ID
#define ONENET_Password   "version=2018-10-31&res=products%2F493136%2Fdevices%2Fesp32-device1&et=1741490120&method=md5&sign=wscxn0OWnKxbxQ7mae3CLQ%3D%3D"

//设备上传数据的post主题
#define ONENET_TOPIC_PROP_POST "$sys/" ONENET_UserName "/" ONENET_clientld "/dp/post/json"

#define ONENET_TOPIC_DP_Publish  "$sys/493136/esp32-device1/dp/post/json"
#define ONENET_TOPIC_DP_Sub      "$sys/493136/esp32-device1/dp/post/json/+"
#define ONENET_TOPIC_CMD_Sub     "$sys/493136/esp32-device1/cmd/#"

//这是post上传数据使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":123,\"dp\":%s}"

static EventGroupHandle_t s_wifi_event_group;

static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "MQTT";
static const char *TAG2 = "smartconfig";

// static EventGroupHandle_t s_cmd_event_group;
static const int RED_BIT = BIT3;
static const int BLUE_BIT = BIT4;

bool send_cycle = false;

typedef struct {
    int timer_group;
    int timer_idx;
    int alarm_interval;
    bool auto_reload;
} example_timer_info_t;

#define RMT_TX_NUM 8 //WS2812 control pin
#define RMT_TX_CHANNEL RMT_CHANNEL_0
#define EXAMPLE_CHASE_SPEED_MS (10)
#define LED_STRIP_NUM 1
#define COLOR_RED 9
#define COLOR_GREE 8
#define COLOR_BULE 10
#define COLOR_PURPLE 11
#define COLOR_ORANGE 12

#define Lamp_Open 13
#define lamp_close 14
#define lamp_speed_Up 15
#define lamp_speed_down 16

#define ligth_down 18
#define ligth_up 19
struct WS2812_COLOR
{
	uint8_t lamp;
	uint8_t ligth_rank;
	uint8_t lamp_speed;
	uint32_t red;
	uint32_t green;
	uint32_t blue;
};

static led_strip_t *strip;

struct WS2812_COLOR WS2812_RGB;

/**
 * @brief A sample structure to pass events from the timer ISR to task
 *
 */
typedef struct {
    example_timer_info_t info;
    uint64_t timer_counter_value;
} example_timer_event_t;



static void smartconfig_example_task(void * parm);
static void led_cmd_task(void * parm);

void RGB16for10(struct WS2812_COLOR *RGB, uint32_t reb_16)
{
	uint32_t rgb_16 = reb_16;
	RGB->blue = rgb_16 & 0Xff;

	rgb_16 = rgb_16 >> 8;
	RGB->green = rgb_16 & 0xff;

	rgb_16 = rgb_16 >> 8;

	RGB->red = rgb_16 & 0xff;
}

void set_rgb(uint32_t rgb_24bit, uint8_t ligth_rank)
{
	RGB16for10(&WS2812_RGB, rgb_24bit);
	ligth_rank = 21 - ligth_rank;
	for (int i = 0; i < LED_STRIP_NUM; i++)
	{
		strip->set_pixel(strip, i, WS2812_RGB.red / ligth_rank, WS2812_RGB.green / ligth_rank, WS2812_RGB.blue / ligth_rank);
	}

	strip->refresh(strip, 10);
}

void init_led()
{
	rmt_config_t config = RMT_DEFAULT_CONFIG_TX(RMT_TX_NUM, RMT_TX_CHANNEL);
	// set counter clock to 40MHz
	config.clk_div = 2;
	ESP_ERROR_CHECK(rmt_config(&config));
	ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));

	// install ws2812 driver
	led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t)config.channel);
	strip = led_strip_new_rmt_ws2812(&strip_config);
	if (!strip)
	{
		ESP_LOGE(TAG, "install WS2812 driver failed");
	}
	// Clear LED strip (turn off all LEDs)
	ESP_ERROR_CHECK(strip->clear(strip, 100));
    
}


static void log_error_if_nonzero(const char * message, int error_code)
{
    if (error_code != 0) {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

static int single_read(void *arg)
{
    int adc1_reading[1] = {0};
    adc1_reading[0] = adc1_get_raw(ADC1_CHANNEL_0);
    // vout = (adc1_reading[0] * 2500.00)/4095.00;
    // ESP_LOGI(TAG_CH[0], "%x vout mv is %f", adc1_reading[0],vout);
    return  adc1_reading[0];
}


static bool IRAM_ATTR system_timer_callback(void* arg)
{
    BaseType_t high_task_awoken = pdFALSE;
    send_cycle = true;
    return high_task_awoken == pdTRUE; // return whether we need to yield at the end of ISR
}

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) {
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
        ESP_LOGI(TAG2, "Scan done");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG2, "Found channel");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
        ESP_LOGI(TAG2, "Got SSID and password");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config;
        uint8_t ssid[33] = { 0 };
        uint8_t password[65] = { 0 };
        uint8_t rvd_data[33] = { 0 };

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true) {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP_LOGI(TAG2, "SSID:%s", ssid);
        ESP_LOGI(TAG2, "PASSWORD:%s", password);
        if (evt->type == SC_TYPE_ESPTOUCH_V2) {
            ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );
            ESP_LOGI(TAG2, "RVD_DATA:");
            for (int i=0; i<33; i++) {
                printf("%02x ", rvd_data[i]);
            }
            printf("\n");
        }

        ESP_ERROR_CHECK( esp_wifi_disconnect() );
        ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
        printf("ready to connect!\r\n");
        esp_wifi_connect();
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}

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;
    char cmdbuf[20];
    // 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, "/topic/qos1", "data_3", 0, 1, 0);
            // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

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

            msg_id = esp_mqtt_client_subscribe(client, ONENET_TOPIC_CMD_Sub, 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");
            // esp_mqtt_client_start(client);
            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);
            
            sprintf(cmdbuf,"%.*s",event->data_len,event->data);
            if(strstr(cmdbuf, ":ledred")){
                xEventGroupSetBits(s_wifi_event_group, RED_BIT);
            }
            else if(strstr(cmdbuf, ":ledblue")){
                xEventGroupSetBits(s_wifi_event_group, BLUE_BIT);
            }
            break;
        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
                log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
                log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
                log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
                ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));

            }
            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)
{
    int msg_id;
    int adc_value;
    float adc_mv;
    /* ADC */
    adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
    adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
    /* */
    esp_mqtt_client_config_t mqtt_cfg = {
        // .uri = ONENET_MqttServer,
        .host = "mqtts.heclouds.com",
        // .uri = "mqtt://broker.emqx.io",
        .client_id = ONENET_clientld,
        .username = ONENET_UserName,
        .password = ONENET_Password,
        .port = 1883,
    };
#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);

    // char *adc_head ="my adc value is:";
    // char *adc_tail ="mv";
    // char adc_publish[25] = {0};

    // int thread;
    float T,H;
    
    char jsonBuf[100];
    char databuf[80];

    while (1)
    {
        if(send_cycle){
            send_cycle = false;
            adc_value = single_read(NULL);
            adc_mv = (adc_value * 2500.00)/4095.00;
            
            SHT2X_THMeasure(I2C_MASTER_NUM);
            // if(thread == ESP_ERR_TIMEOUT){}
            // else{
                T =(getTemperature()/100.0);
                H =(getHumidity()/100.0);
                printf("this is my th test, %4.2f C\r\n%4.2f %%\r\n",T,H); 
            // }

            sprintf(databuf, "{ \"tem\":[{\"v\":%.2f}] ,\"hum\":[{\"v\":%.2f}] ,\"adc\":[{\"v\":%.2f}] }", T,H,adc_mv); 
            sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, databuf);
            // sprintf(adc_publish,"%s %.2f %s",adc_head,adc_mv,adc_tail);
            msg_id = esp_mqtt_client_publish(client, ONENET_TOPIC_DP_Publish, jsonBuf , 0, 1, 0);
            ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        }
        
        vTaskDelay(1);
    }
}


static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    /*
    just for test  ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
    esp_wifi_restore 使用需要在 esp_wifi_init 之后
    */
    // esp_wifi_restore();

    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() );

    xTaskCreate(led_cmd_task, "led_cmd_task", 2048, NULL, 2, NULL);
}


/**
 * @brief Initialize selected timer of timer group
 *
 * @param group Timer Group number, index from 0
 * @param timer timer ID, index from 0
 * @param auto_reload whether auto-reload on alarm event
 * @param timer_interval_sec interval of alarm
 */
static void example_tg_timer_init(int group, int timer, bool auto_reload, int timer_interval_sec)
{
    /* Select and initialize basic parameters of the timer */
    timer_config_t config = {
        .divider = 16,
        .counter_dir = TIMER_COUNT_UP,
        .counter_en = TIMER_PAUSE,
        .alarm_en = TIMER_ALARM_EN,
        .auto_reload = auto_reload,
    }; // default clock source is APB
    timer_init(group, timer, &config);

    /* Timer's counter will initially start from value below.
       Also, if auto_reload is set, this value will be automatically reload on alarm */
    timer_set_counter_value(group, timer, 0);

    /* Configure the alarm value and the interrupt on alarm. */
    timer_set_alarm_value(group, timer, timer_interval_sec * (TIMER_BASE_CLK / 16));
    timer_enable_intr(group, timer);

    example_timer_info_t *timer_info = calloc(1, sizeof(example_timer_info_t));
    timer_info->timer_group = group;
    timer_info->timer_idx = timer;
    timer_info->auto_reload = auto_reload;
    timer_info->alarm_interval = timer_interval_sec;
    timer_isr_callback_add(group, timer, system_timer_callback, timer_info, 0);

    timer_start(group, timer);
}

static void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;

    wifi_config_t myconfig = {0};
    esp_wifi_get_config(ESP_IF_WIFI_STA,&myconfig);
    if(strlen((char *)myconfig.sta.ssid) > 0){      
        ESP_LOGI(TAG2, "already set SSID:%s,connect now!...",myconfig.sta.ssid);
        esp_wifi_connect();
    }else{
        ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
        smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
        ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    }
 
    while (1) {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if(uxBits & CONNECTED_BIT) {
            ESP_LOGI(TAG2, "WiFi Connected to ap");
            example_tg_timer_init(TIMER_GROUP_0, TIMER_0, true, 5);
            vTaskDelete(NULL);
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            ESP_LOGI(TAG2, "smartconfig over");
            esp_smartconfig_stop();
            example_tg_timer_init(TIMER_GROUP_0, TIMER_0, true, 5);
            vTaskDelete(NULL);
        }
    }
}

static void led_cmd_task(void * parm)
{
    EventBits_t uxBits;
    while (1) {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, RED_BIT | BLUE_BIT, true, false, portMAX_DELAY);
        if(uxBits & RED_BIT) {
            ESP_LOGI(TAG, "LED Turn RED"); 
            set_rgb(0x00FF00, WS2812_RGB.ligth_rank);         
        }
        if(uxBits & BLUE_BIT) {
            ESP_LOGI(TAG, "LED Turn BLUE");
            set_rgb(0X0000ff, WS2812_RGB.ligth_rank);
        }
        // set_rgb(0Xff0000, WS2812_RGB.ligth_rank);//绿色
        // set_rgb(0x00FF00, WS2812_RGB.ligth_rank); //红色
        // set_rgb(0X0000ff, WS2812_RGB.ligth_rank);//蓝色
        //set_rgb(0XF05308, WS2812_RGB.ligth_rank); //黄绿色
    }
}



void app_main(void)
{
    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());

    ESP_ERROR_CHECK(i2c_master_init());

    button_start();

    init_led();
       
    initialise_wifi();

    mqtt_app_start();
}

你可能感兴趣的:(ESP32-C3,物联网,iot,ESP32-C3,MQTT,ONENET)