衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何移植MQTT物聯(lián)網通信協(xié)議

電子發(fā)燒友開源社區(qū) ? 來源:HarmonyOS官方合作社區(qū) ? 作者:HarmonyOS官方合作社 ? 2022-03-03 09:26 ? 次閱讀

摘要

本文簡單介紹如何移植MQTT

適合群體

適用于潤和Hi3861開發(fā)板的開發(fā)人員。

1、MQTT介紹

MQTT 是當前最主流的物聯(lián)網通信協(xié)議,需要物聯(lián)網云平臺,例如華為云、阿里云、移動OneNET都支持mqtt。而Hi3861則是一款專為IoT應用場景打造的芯片。本節(jié)主要講如何在鴻蒙系統(tǒng)中通過移植第3方軟件包 paho mqtt去實現(xiàn)MQTT協(xié)議功能,最后會給出測試驗證。為后續(xù)的物聯(lián)網項目打好基礎。

友情預告,本節(jié)內容較多,源碼也貼出來了,大家最好先看一遍,然后再操作一次。

已經移植好的MQTT源碼:

2、MQTT移植

如果不想要自己移植的,可以跳過本節(jié)。MQTT 全稱為 Message Queuing Telemetry Transport(消息隊列遙測傳輸)是一種基于發(fā)布/訂閱范式的二進制“輕量級”消息協(xié)議,由IB公司發(fā)布。針對于網絡受限和嵌入式設備而設計的一種數(shù)據(jù)傳輸協(xié)議。MQTT最大優(yōu)點在于,可以以極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。作為一種低開銷、低帶寬占用的即時通訊協(xié)議,使其在物聯(lián)網、小型設備、移動應用等方面有較廣泛的應用。MQTT模型如圖所示。

更多MQTT協(xié)議的介紹見這篇文章:MQTT 協(xié)議開發(fā)入門

如何移植MQTT物聯(lián)網通信協(xié)議

1)下載paho mqtt軟件包,添加到鴻蒙代碼中

paho mqtt-c 是基于C語言實現(xiàn)的MQTT客戶端,非常適合用在嵌入式設備上。首先下載源碼:

下載之后解壓,會得到這么一個文件夾:

如何移植MQTT物聯(lián)網通信協(xié)議

如何在鴻蒙系統(tǒng)中移植 Paho-MQTT 實現(xiàn)MQTT協(xié)議-鴻蒙HarmonyOS技術社區(qū)

我們在鴻蒙系統(tǒng)源碼的 third_party 文件夾下創(chuàng)建一個 pahomqtt 文件夾,然后把解壓后的所有文件都拷貝到 pahomqtt 文件夾下。

下一步,我們在pahomqtt 文件夾下面新建BUILD.gn文件,用來構建編譯。其內容如下:

# Copyright (c) 2020 Huawei Device Co., Ltd.# Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at##   http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.
import("http://build/lite/config/component/lite_component.gni")import("http://build/lite/ndk/ndk.gni")
config("pahomqtt_config") {  include_dirs = [    "MQTTPacket/src",    "MQTTClient-C/src",    "MQTTClient-C/src/liteOS",    "http://kernel/liteos_m/components/cmsis/2.0",  ]}
pahomqtt_sources = ["MQTTClient-C/src/liteOS/MQTTLiteOS.c","MQTTClient-C/src/MQTTClient.c",
"MQTTPacket/src/MQTTConnectClient.c","MQTTPacket/src/MQTTConnectServer.c","MQTTPacket/src/MQTTDeserializePublish.c","MQTTPacket/src/MQTTFormat.c","MQTTPacket/src/MQTTPacket.c","MQTTPacket/src/MQTTSerializePublish.c","MQTTPacket/src/MQTTSubscribeClient.c","MQTTPacket/src/MQTTSubscribeServer.c","MQTTPacket/src/MQTTUnsubscribeClient.c","MQTTPacket/src/MQTTUnsubscribeServer.c",]
lite_library("pahomqtt_static") {  target_type = "static_library"  sources = pahomqtt_sources  public_configs = [ ":pahomqtt_config" ]}
lite_library("pahomqtt_shared") {  target_type = "shared_library"  sources = pahomqtt_sources  public_configs = [ ":pahomqtt_config" ]}
ndk_lib("pahomqtt_ndk") {  if (board_name != "hi3861v100") {    lib_extension = ".so"    deps = [      ":pahomqtt_shared"    ]  } else {    deps = [      ":pahomqtt_static"    ]  }  head_files = [    "http://third_party/pahomqtt"  ]}

向右滑動查看完整代碼

2)移植

我們使用到的是MQTTClient-C的代碼,該代碼支持多線程。

(1)創(chuàng)建LiteOS文件夾

MQTT已經提供了Linuxfreertos的移植,這里我們參考,新建文件夾:third_partypahomqttMQTTClient-CsrcliteOS,里面存放兩個文件:MQTTLiteOS.c 和 MQTTLiteOS.h,內容如下:

#include "MQTTLiteOS.h"
//用來創(chuàng)建線程int ThreadStart(Thread* thread, void (*fn)(void*), void* arg){ int rc = 0; thread = thread;
 osThreadAttr_t attr;
  attr.name = "MQTTTask";  attr.attr_bits = 0U;  attr.cb_mem = NULL;  attr.cb_size = 0U;  attr.stack_mem = NULL;  attr.stack_size = 2048;  attr.priority = osThreadGetPriority(osThreadGetId());
  rc = (int)osThreadNew((osThreadFunc_t)fn, arg, &attr);
 return rc;}//定時器初始化void TimerInit(Timer* timer){ timer->end_time = (struct timeval){0, 0};}
char TimerIsExpired(Timer* timer){ struct timeval now, res; gettimeofday(&now, NULL); timersub(&timer->end_time, &now, &res); return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);}

void TimerCountdownMS(Timer* timer, unsigned int timeout){ struct timeval now; gettimeofday(&now, NULL); struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000}; timeradd(&now, &interval, &timer->end_time);}

void TimerCountdown(Timer* timer, unsigned int timeout){ struct timeval now; gettimeofday(&now, NULL); struct timeval interval = {timeout, 0}; timeradd(&now, &interval, &timer->end_time);}

int TimerLeftMS(Timer* timer){ struct timeval now, res; gettimeofday(&now, NULL); timersub(&timer->end_time, &now, &res); //printf("left %d ms
", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;}
void MutexInit(Mutex* mutex){ mutex->sem = osSemaphoreNew(1, 1, NULL);}
int MutexLock(Mutex* mutex){ return osSemaphoreAcquire(mutex->sem, LOS_WAIT_FOREVER);}
int MutexUnlock(Mutex* mutex){ return osSemaphoreRelease(mutex->sem);}
//接受數(shù)據(jù)int ohos_read(Network* n, unsigned char* buffer, int len, int timeout_ms){ struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000}; if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0)) {  interval.tv_sec = 0;  interval.tv_usec = 100; }
 setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
 int bytes = 0; while (bytes < len) {  int rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0);  if (rc == -1)  {   if (errno != EAGAIN && errno != EWOULDBLOCK)    bytes = -1;   break;  }  else if (rc == 0)  {   bytes = 0;   break;  }  else   bytes += rc; } return bytes;}
//寫數(shù)據(jù)int ohos_write(Network* n, unsigned char* buffer, int len, int timeout_ms){ struct timeval tv;
 tv.tv_sec = 0; /* 30 Secs Timeout */ tv.tv_usec = timeout_ms * 1000; // Not init'ing this can cause strange errors
 setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval)); int rc = send(n->my_socket, buffer, len, 0); return rc;}
//網絡初始化void NetworkInit(Network* n){ n->my_socket = 0; n->mqttread = ohos_read; n->mqttwrite = ohos_write;}
//網絡連接int NetworkConnect(Network* n, char* addr, int port){ int type = SOCK_STREAM; struct sockaddr_in address; int rc = -1; sa_family_t family = AF_INET; struct addrinfo *result = NULL; struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
 if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0) {  struct addrinfo* res = result;
  /* prefer ip4 addresses */  while (res)  {   if (res->ai_family == AF_INET)   {    result = res;    break;   }   res = res->ai_next;  }
  if (result->ai_family == AF_INET)  {   address.sin_port = htons(port);   address.sin_family = family = AF_INET;   address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;  }  else   rc = -1;
  freeaddrinfo(result); }
 if (rc == 0) {  n->my_socket = socket(family, type, 0);  if (n->my_socket != -1)   rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address));  else   rc = -1; }
 return rc;}

void NetworkDisconnect(Network* n){ close(n->my_socket);}

向右滑動查看完整代碼

至此我們移植基本結束。

3、代碼測試

測試代碼比較好寫。主要是3個文件,內容我都貼出來了:

(1)BUILD.gn文件內容:

static_library("mqtt_test") {  sources = [    "mqtt_test.c",    "mqtt_entry.c"  ]
  include_dirs = [    "http://utils/native/lite/include",    "http://kernel/liteos_m/components/cmsis/2.0",    "http://base/iot_hardware/interfaces/kits/wifiiot_lite",    "http://vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include",    "http://foundation/communication/interfaces/kits/wifi_lite/wifiservice",    "http://third_party/pahomqtt/MQTTPacket/src",    "http://third_party/pahomqtt/MQTTClient-C/src",    "http://third_party/pahomqtt/MQTTClient-C/src/liteOS",  ]#表示需要a_myparty 軟件包  deps = [    "http://third_party/pahomqtt:pahomqtt_static",  ]}

向右滑動查看完整代碼

(2)mqtt_entry.c文件

主要是進行熱點連接,因為我們要使用MQTT需要用到網絡。熱點連接的代碼之前在第9章已經講說,這里就不完全貼了,代碼倉庫也有,主要的代碼部分:

void wifi_sta_task(void *arg){  arg = arg;    //連接熱點  hi_wifi_start_sta();
  while(wifi_ok_flg == 0)  {    usleep(30000);  }      usleep(2000000);
  //開始進入MQTT測試  mqtt_test();}

向右滑動查看完整代碼

(3)mqtt_test.c 文件則是編寫了一個簡單的MQTT測試代碼

其中測試用的mqtt服務器是我自己的服務器:5.196.95.208,大家也可以改成自己的。

#include #include #include "ohos_init.h"#include "cmsis_os2.h"
#include "hi_wifi_api.h"#include "lwip/ip_addr.h"#include "lwip/netifapi.h"#include "lwip/sockets.h"
#include "MQTTClient.h"

static MQTTClient mq_client;
 unsigned char *onenet_mqtt_buf; unsigned char *onenet_mqtt_readbuf; int buf_size;
Network n;MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 
//消息回調函數(shù)void mqtt_callback(MessageData *msg_data){  size_t res_len = 0;  uint8_t *response_buf = NULL;  char topicname[45] = { "$crsp/" };
  LOS_ASSERT(msg_data);
  printf("topic %.*s receive a message
", msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data);
  printf("message is %.*s
", msg_data->message->payloadlen, msg_data->message->payload);
}
int mqtt_connect(void){ int rc = 0;   NetworkInit(&n); NetworkConnect(&n, "5.196.95.208", 1883);
  buf_size = 2048;  onenet_mqtt_buf = (unsigned char *) malloc(buf_size);  onenet_mqtt_readbuf = (unsigned char *) malloc(buf_size);  if (!(onenet_mqtt_buf && onenet_mqtt_readbuf))  {    printf("No memory for MQTT client buffer!");    return -2;  }
 MQTTClientInit(&mq_client, &n, 1000, onenet_mqtt_buf, buf_size, onenet_mqtt_readbuf, buf_size);   MQTTStartTask(&mq_client);

  data.keepAliveInterval = 30;  data.cleansession = 1; data.clientID.cstring = "ohos_hi3861"; data.username.cstring = "123456"; data.password.cstring = "222222";
 data.keepAliveInterval = 10; data.cleansession = 1;   mq_client.defaultMessageHandler = mqtt_callback;
 //連接服務器 rc = MQTTConnect(&mq_client, &data);
 //訂閱消息,并設置回調函數(shù) MQTTSubscribe(&mq_client, "ohossub", 0, mqtt_callback);
 while(1) {  MQTTMessage message;
  message.qos = QOS1;  message.retained = 0;  message.payload = (void *)"openharmony";  message.payloadlen = strlen("openharmony");
  //發(fā)送消息  if (MQTTPublish(&mq_client, "ohospub", &message) < 0)  {   return -1;  } }
 return 0;}

void mqtt_test(void){  mqtt_connect();}

向右滑動查看完整代碼

到這里就完成了代碼部分,可以開始編譯了。

4、編譯

這里我們需要先下載一個 Windows電腦端的 MQTT客戶端,這樣我們就可以用電腦訂閱開發(fā)板的MQTT主題信息了。

我們選擇這一個:

如何移植MQTT物聯(lián)網通信協(xié)議

弄完后打開軟件,按圖操作:

如何移植MQTT物聯(lián)網通信協(xié)議

此時我們去查看 我們電腦端的MQTT客戶端軟件,可以看到右邊已經有接收MQTT信息了,主題未 ohospub,消息內容為 openharmony,說明實驗成功。

電腦發(fā)送主題為ohossub,內容為123456,查看串口打印,可以看到也收到了數(shù)據(jù)。

如何移植MQTT物聯(lián)網通信協(xié)議

本節(jié)移植MQTT的教程就到這里了,下一篇我們給大家分享:OneNET云接入,歡迎大家持續(xù)關注哦~

原文標題:OpenHarmony輕量系統(tǒng)開發(fā)【11】移植MQTT

文章出處:【微信公眾號:HarmonyOS官方合作社區(qū)】歡迎添加關注!文章轉載請注明出處。

審核編輯:湯梓紅


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 通信
    +關注

    關注

    18

    文章

    6070

    瀏覽量

    136419
  • 物聯(lián)網

    關注

    2913

    文章

    44923

    瀏覽量

    376984
  • MQTT
    +關注

    關注

    5

    文章

    653

    瀏覽量

    22690

原文標題:OpenHarmony輕量系統(tǒng)開發(fā)【11】移植MQTT

文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發(fā)燒友開源社區(qū)】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    聯(lián)網通信協(xié)議的詳解及選擇建議

    通信聯(lián)網來說十分關鍵,無論是近距離無線傳輸技術還是移動通信技術,甚至是LPWAN都影響著聯(lián)網
    發(fā)表于 05-23 14:23 ?6.7w次閱讀
    <b class='flag-5'>物</b><b class='flag-5'>聯(lián)網通信協(xié)議</b>的詳解及選擇建議

    如何在鴻蒙系統(tǒng)中移植 Paho-MQTT 實現(xiàn)MQTT協(xié)議

    MQTT 是當前最主流的聯(lián)網通信協(xié)議,需要聯(lián)網云平臺,例如華為云、阿里云、移動OneNET都支持mq
    發(fā)表于 10-23 22:57

    8種聯(lián)網通信協(xié)議介紹

    聯(lián)網生態(tài)系統(tǒng)的核心組成部分是連接和通信。聯(lián)網使遠程和分散物體(設備,傳感器節(jié)點,網關單元,云服務器)之間的連接和
    發(fā)表于 12-24 06:13

    MQTT協(xié)議及其應用開發(fā)介紹

    聯(lián)網是指什么?聯(lián)網通信協(xié)議包括哪些?MQTT協(xié)議是由哪些部分組成的?
    發(fā)表于 09-24 07:44

    聯(lián)網常見的通信協(xié)議有哪些?

    聯(lián)網常見的通信協(xié)議有哪些?
    發(fā)表于 11-05 09:12

    常見的聯(lián)網通信協(xié)議藍牙簡單對比

    @TOC淺析聯(lián)網(智能家居)無線通信協(xié)議聯(lián)網無線傳輸方案產品開發(fā),通信協(xié)議(生態(tài))選擇至關重
    發(fā)表于 01-11 07:24

    聯(lián)網的基石-MQTT協(xié)議初識

    。MQTT 協(xié)議 是基于發(fā)布/訂閱模式的聯(lián)網通信協(xié)議,憑借簡單易實現(xiàn)、支持 QoS、報文小等特點,占據(jù)了
    發(fā)表于 09-08 16:03

    聯(lián)網通信協(xié)議

    ? MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)? 輕量級通信協(xié)議? 適用資源受限設備,低帶寬,高延時,不穩(wěn)定網絡中進行消息傳輸? 運行
    發(fā)表于 09-11 06:18

    mqtt-v3.1.1版協(xié)議

    mqtt-v3.1.1版協(xié)議,英文版,時間2014.10.29,聯(lián)網通信協(xié)議MQTT
    發(fā)表于 10-29 11:22 ?0次下載

    工業(yè)4.0聯(lián)網通信協(xié)議你了解多少

    聯(lián)網連接是整個工業(yè)聯(lián)網(IIOT)系統(tǒng)的主干,因此在選擇將要使用的聯(lián)網通信協(xié)議類型時,應該
    發(fā)表于 06-21 09:54 ?4809次閱讀

    最常用的聯(lián)網通信協(xié)議有哪些

    隨著聯(lián)網設備數(shù)量的持續(xù)增加,這些設備之間的通信或連接已成為一個重要的思考課題。根據(jù)Gartner的研究,到2020年,聯(lián)網設備數(shù)量將達到
    的頭像 發(fā)表于 01-20 09:29 ?8964次閱讀

    聯(lián)網通信協(xié)議的種類與其區(qū)別

    聯(lián)網通信協(xié)議種類繁多,不同層次的通信協(xié)議因硬件和連接設置而異,但在某些功能上是相同的,很多人很難區(qū)分。我們來比較一下這些通信協(xié)議的區(qū)別。
    發(fā)表于 06-25 09:42 ?3434次閱讀

    聯(lián)網通信協(xié)議基礎知識合集

    本文介紹了幾個可用的聯(lián)網通信協(xié)議,它們具有不同的性能、數(shù)據(jù)速率、覆蓋范圍、功率和內存,而且每一種協(xié)議都有各自的優(yōu)點和或多或少的缺點。其中一些通信協(xié)議只適合小型家用電器,而其他一些
    的頭像 發(fā)表于 03-23 14:32 ?1241次閱讀

    聯(lián)網通信協(xié)議知多少

    尤其重要,是雙方實體完成通信或服務所必須遵循的規(guī)則和約定。本文介紹了幾個可用的聯(lián)網通信協(xié)議,它們具有不同的性能、數(shù)據(jù)速率、覆蓋范圍、功率和內存,而且每一種協(xié)議都有
    的頭像 發(fā)表于 03-11 09:55 ?1358次閱讀
    <b class='flag-5'>物</b><b class='flag-5'>聯(lián)網通信協(xié)議</b>知多少

    一文了解聯(lián)網通信協(xié)議MQTT如何助力無線模塊廣泛連接

    引言:隨著聯(lián)網技術的飛速發(fā)展,無線模塊在連接各種智能設備、實現(xiàn)數(shù)據(jù)交互中扮演著至關重要的角色。為了有效滿 足聯(lián)網通信的多樣化需求,一種輕量級、高效且可靠的消息傳輸
    的頭像 發(fā)表于 06-07 16:10 ?1319次閱讀
    一文了解<b class='flag-5'>物</b><b class='flag-5'>聯(lián)網通信協(xié)議</b>之<b class='flag-5'>MQTT</b>如何助力無線模塊廣泛連接
    24山六十日吉凶| 大发888官方网页| 百家乐官网娱乐城返水| 澳门百家乐单注下限| 足球波胆| 永利博百家乐官网的玩法技巧和规则 | 襄汾县| 金公主百家乐现金网| 云顶娱乐| 波音百家乐游戏| 欧博娱乐| 百家乐路纸发表区| 太阳城娱乐网站| 澳门百家乐海洋阿强| 百家乐官网有没有绝| 百家乐菲律宾| 百家乐官网学院| 大发888注册页| 海尔百家乐官网的玩法技巧和规则 | 赌场百家乐攻略| 百家乐官网如何看牌| 百家乐皇室百家乐| 百家乐官网群号| 大发888怎么进不去| 九运2024年-2043年| 九江市| 百家乐必胜打| 百家乐官网7scs娱乐场| 金煌棋牌官网| 澳门百家乐破解| 真人百家乐官网什么平台| 大发888客服qq号| 风水24山读法| 百家乐官网怎么刷反水| 威尼斯人娱乐城游戏| 百家乐官网群的微博| bet365投注| 百家乐百博亚洲| 百合百家乐官网的玩法技巧和规则| 博彩通天上人间| 金都百家乐的玩法技巧和规则 |