ESP32 web 对接华为云平台–MQTT协议

作者 : admin 本文共6578个字,预计阅读时间需要17分钟 发布时间: 2024-06-11 共2人阅读

文章目录

  • 前言
  • 一、MQTT协议
  • 二、如何使用MQTT协议对接华为云
    • 1.注册华为云账号
    • 2.设备接入中创建资源空间
    • 3.如何连接
    • 4.通过MQTT.fx工具做初步对接
      • 4.1 设置连接信息
      • 4.2 连接平台
    • 5.查看平台设备信息
  • 三. 设备测对接平台
    • 1.ESP测引入MQTT库
    • 2.编码
      • 2.1前端编码修改
      • 2.2 后端接口修改
    • 3.MQTT编码
    • 4.添加编译文件
    • 5.正常编译烧写
    • 6. 结果展示
  • 总结

前言

今天这篇文章,对于刚接触物联网协议或者刚接触ESP这款模组并且想对接云平台的人特别有帮助。还希望大家耐心的看完。
在今天的实验里面,你需要有三个概念。
第一什么是MQTT协议,
第二 MQTT协议又是如何连接的,
第三点如何在官方的web demo上添加后端服务和前端页面的接口,实验在线MQTT数据传输。


一、MQTT协议

MQTT协议是一个物联网协议,简单来说就是设备和云平台之间的一种通信传输方式,就好比,在中国大家用中国话来交流,在美国用美国话交流。这就对应着两种通信协议。具体的细节,我的建议还是去百度看看。对于初学者,有这个通信的概念即可。

二、如何使用MQTT协议对接华为云

1.注册华为云账号

这个就不说了,去百度找华为云的官方,免费注册。

2.设备接入中创建资源空间

这个可以百度一下华为云设备接入MQTT设备注册

3.如何连接

首先,我们要参考文档 。在这个文档里面,我们可以看到,我们连接的时候需要填写设备ID,用户名和密码。
ESP32 web 对接华为云平台–MQTT协议插图

其次,怎么获取这一套数据,是目前我们要思考的问题。好在官方直接给出了加密运算的方式。参数计算链接

在下图中,重点关注设备ID和密钥,密钥是在你创建设备的时候就有的
ESP32 web 对接华为云平台–MQTT协议插图(1)

注意上图和下图的设备ID不一样,这是因为我想要告诉大家这个密钥在什么地方,单独创建了一下。

ESP32 web 对接华为云平台–MQTT协议插图(2)

通过下面的页面,我们填入上述的设备ID和密钥,获取新的三元素,我们就可以对接设备。

ESP32 web 对接华为云平台–MQTT协议插图(3)

4.通过MQTT.fx工具做初步对接

4.1 设置连接信息

ESP32 web 对接华为云平台–MQTT协议插图(4)

4.2 连接平台

ESP32 web 对接华为云平台–MQTT协议插图(5)

5.查看平台设备信息

ESP32 web 对接华为云平台–MQTT协议插图(6)

三. 设备测对接平台

1.ESP测引入MQTT库

官方的MQTT demo路径 /esp/esp-idf/examples/protocols/mqtt

在上述的方案中,我们已经完成了电脑模拟设备对接的过程。接下来,我们要用我们的ESP模组完成云平台的对接。还是用之前的web demo。

2.编码

2.1前端编码修改

注意我是将Chart.vue中的内容注释掉替换成了下面的内容

<template>
<v-container>
<v-layout text-xs-center wrap>
<v-flex xs12 sm6 offset-sm3>
<v-card hover>
<v-card-title style="font-weight: 800; font-size: 18px">
阿里云平台数据发送测试
</v-card-title>
<div style="width: 90%; margin: 0 auto; padding: 20px">
<v-text-field
v-model="mesdata"
label="测试数据"
hint="输入测试数据"
></v-text-field>
<v-btn
block
color="success"
size="large"
type="submit"
@click="submitdata"
>
提交
</v-btn>
</div>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
export default {
data() {
return {
mesdata: null,
};
},
methods: {
submitdata() {
this.$ajax
.post("/api/v1/mqtt/echo", {
data: this.mesdata,
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
this.mesdata = "";
},
},
destroyed() {},
mounted() {},
};
</script>

2.2 后端接口修改

加入一个后端接口,方便前端界面传输数据

// mqtt_send_data_toserver 是我自己封装的一个发送函数,代码都会给大家
extern void mqtt_send_data_toserver(char *message);
static esp_err_t mqtt_echo_handler(httpd_req_t *req)
{
int total_len = req->content_len;
int cur_len = 0;
char message[256] = {0};
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
int received = 0;
if (total_len >= SCRATCH_BUFSIZE)
{
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
return ESP_FAIL;
}
while (cur_len < total_len)
{
received = httpd_req_recv(req, buf + cur_len, total_len);
if (received <= 0)
{
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
return ESP_FAIL;
}
cur_len += received;
}
buf[total_len] = '\0';
cJSON *root = cJSON_Parse(buf);
//注意这里,这边是为了解析前端页面的数据
strcpy(message, cJSON_GetObjectItem(root, "data")->valuestring);
cJSON_Delete(root);
httpd_resp_sendstr(req, "Post control value successfully");
mqtt_send_data_toserver(message);
return ESP_OK;
}

在start_rest_server 函数中添加下面的代码 (注册解析前端方法到系统中)

    httpd_uri_t mqtt_post_uri = {
.uri = "/api/v1/mqtt/echo",
.method = HTTP_POST,
.handler = mqtt_echo_handler,
.user_ctx = rest_context};
httpd_register_uri_handler(server, &mqtt_post_uri);

3.MQTT编码


/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include 
#include 
#include 
#include 
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "cJSON.h"
#include "esp_log.h"
#include "mqtt_client.h"
#define CLIENTID ""
#define USERNAME ""
#define PASSWORD ""
#define SERVERURL "mqtt://121.36.42.100:1883"
#define PUSHTOPIC "$oc/devices/你的设备ID/sys/properties/report"
esp_mqtt_client_handle_t mqtt_client;
static const char *MQTTTAG = "MQTT";
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(MQTTTAG, "Last error %s: 0x%x", message, error_code);
}
}
void mqtt_send_data_toserver(char *message)
{
int msg_id;
char obj_name[10] = {0};
double rounded = 0;
cJSON *root = cJSON_CreateObject();
// 创建数组对象
cJSON *array = cJSON_CreateArray();
// 创建对象
cJSON *obj = cJSON_CreateObject();
cJSON_AddStringToObject(obj, "service_id", "echo");
cJSON *values = cJSON_CreateObject();
cJSON_AddStringToObject(values, "read", message);
cJSON_AddItemToObject(obj, "properties", values);
// 将对象添加到数组中
cJSON_AddItemToArray(array, obj);
// 将数组添加到根节点中
cJSON_AddItemToObject(root, "services", array);
const char *sys_info = cJSON_Print(root);
ESP_LOGI(MQTTTAG, "%s", sys_info);
msg_id = esp_mqtt_client_publish(mqtt_client, PUSHTOPIC, sys_info, 0, 1, 1);
free((void *)sys_info);
cJSON_Delete(root);
return;
}
static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(MQTTTAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32, base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(MQTTTAG, "MQTT_EVENT_CONNECTED");
mqtt_send_data_toserver("sadsadsadas");
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(MQTTTAG, "MQTT_EVENT_DISCONNECTED");
esp_mqtt_client_reconnect(client);
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(MQTTTAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
/* 退订绑定的服务,目前先不处理 */
ESP_LOGI(MQTTTAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
/* 推送绑定的事件 */
ESP_LOGI(MQTTTAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
/* 数据下发,先不处理 */
ESP_LOGI(MQTTTAG, "MQTT_EVENT_DATA");
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(MQTTTAG, "MQTT_EVENT_ERROR return code %d", event->error_handle->connect_return_code);
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(MQTTTAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(MQTTTAG, "Other event id:%d", event->event_id);
break;
}
}
int mqtt5_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.uri = SERVERURL,
.credentials.client_id = CLIENTID,
.credentials.username = USERNAME,
.credentials.authentication.password = PASSWORD,
.network.disable_auto_reconnect = true};
ESP_LOGI(MQTTTAG, "MQTT Server url:%s Client Id %s", mqtt_cfg.broker.address.uri, mqtt_cfg.credentials.client_id);
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
if (mqtt_client == NULL)
{
return 1;
}
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
return 0;
}

4.添加编译文件

ESP32 web 对接华为云平台–MQTT协议插图(7)

5.正常编译烧写

这个就不再叙述了,查看以往的案例

6. 结果展示

平台端的显示

ESP32 web 对接华为云平台–MQTT协议插图(8)

网页端的发送 (注意 我是修改的Chart.vue 这个文件的内容)

ESP32 web 对接华为云平台–MQTT协议插图(9)

后台日志显示 (按照这个报文形势发送)

ESP32 web 对接华为云平台–MQTT协议插图(10)

{
"services": [{
"service_id": "echo",
"properties": {
"read": "xxxxx"
}
}
]
}

总结

今天完成了ESP 对接华为云的案例,里面还是有点弯弯绕的.有疑问就提出来,我都会回复.
后面再有好玩的案例,再发出来看.

本站无任何商业行为
个人在线分享 » ESP32 web 对接华为云平台–MQTT协议
E-->