文章目錄
- 前言
- 一、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,用戶名和密碼。
其次,怎么獲取這一套數據,是目前我們要思考的問題。好在官方直接給出了加密運算的方式。參數計算鏈接
在下圖中,重點關注設備ID和密鑰,密鑰是在你創建設備的時候就有的
注意上圖和下圖的設備ID不一樣,這是因為我想要告訴大家這個密鑰在什么地方,單獨創建了一下。
通過下面的頁面,我們填入上述的設備ID和密鑰,獲取新的三元素,我們就可以對接設備。
4.通過MQTT.fx工具做初步對接
4.1 設置連接信息
4.2 連接平臺
5.查看平臺設備信息
三. 設備測對接平臺
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-fieldv-model="mesdata"label="測試數據"hint="輸入測試數據"></v-text-field><v-btnblockcolor="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 <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#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.添加編譯文件
5.正常編譯燒寫
這個就不再敘述了,查看以往的案例
6. 結果展示
平臺端的顯示
網頁端的發送 (注意 我是修改的Chart.vue 這個文件的內容)
后臺日志顯示 (按照這個報文形勢發送)
{"services": [{"service_id": "echo","properties": {"read": "xxxxx"}}]
}
總結
今天完成了ESP 對接華為云的案例,里面還是有點彎彎繞的.有疑問就提出來,我都會回復.
后面再有好玩的案例,再發出來看.