如何在x86模拟器和鸿蒙API9如何使用MQTT模块ohos_mqtt

目录

引言

安装失败的原因

如何编译so文件的x86_64版本

下载源代码

 安装NDK

代码编译

安装MQTT软件包

避免MQTT软件包自动升级

设置libs

客户端程序的编写

运行测试

结语

参考文献


引言

在上周的博客(如何在鸿蒙API9和x86模拟器中使用MQTT-CSDN博客)中介绍了我的学生有个需求:他在写鸿蒙APP时无法将MQTT库加入到设备中,由于他没有鸿蒙的真机,只能用DevEco Studio中通过的模拟器来实现,而自带的模拟器只支持API9和API6,而下载的MQTT库是支持API11的。今天就来说说在API9中如何实现MQTT客户端,使用的DevEco Studio版本是3.11。

安装失败的原因

官方有个MQTT软件包:ohpm/mqtt,我写作本文时最新的版本是2.14,针对的是API12。可以将其降级为2.0.5-rc.0或者2.0.6使其支持API9,但是由于其是从C语言版本移植过来的,依赖C语言的库文件(libmqttasync.so),而官方仓库中只提供了ARM版本的,所以在真机上可以用,但是在基于x86的本机模拟器上没法用,会出现”Failure[ERR_INSTALL_PARSE_NATIVE_SO_FAILED]“错误。如果要使用就需要使用NDK重新编译该软件包中C语言文件产生x86可以用的库文件,今天就解决这个问题。

如何编译so文件的x86_64版本

下载源代码

首先需要用git下载mqtt模块的源代码,这里我们下载的是2.0.5版本的源代码,它可以和API9兼容:

git clone -b 2.0.5 --single-branch https://gitee.com/openharmony-tpc/ohos_mqtt.git

由于代码中引用了另外两个子模块,所以也需要下载:

git submodule update --init --recursive

代码下载后,可以看到D:\DevEcoStudioProjects\ohos_mqtt\ohos_Mqtt\src\main\cpp目录中包括NAPI相关的代码。OpenHarmony NAPI 提供了一套接口,使得 ArkTS/TS/JS 与 C/C++ 之间可以进行交互。通过 NAPI,可以实现例如网络通信、串口访问、多媒体解码、传感器数据收集等功能。

 安装NDK

要编译NAPI相关的C语言代码就需要安装OpenHarmony NDK。如果以前在DevEco Studio中建立过Native C++工程,则DevEco Studio会自动安装NDK。如果没有安装过,也可以手工安装,选择File|Settings,在其中SDK部分选择Native。

代码编译

在Windows下打开PowerShell,进入C++语言所在目录,使用下面的命令调用CMake生成makefile(命令行中的具体路径取决于用户设置)。

D:\Huawei\SDK\OpenHarmony\9\native\build-tools\cmake\bin\cmake -G Ninja -B out -DCMAKE_TOOLCHAIN_FILE=D:\Huawei\SDK\OpenHarmony\9\native\build\cmake\ohos.toolchain.cmake -DCMAKE_MAKE_PROGRAM=D:\Huawei\SDK\OpenHarmony\9\native\build-tools\cmake\bin\ninja.exe -DCMAKE_BUILD_WITH_INSTALL_RPATH=true -DOHOS_ARCH=x86_64

命令行中的OHOS_ARCH参数指定生成代码的操作系统的类型,其类型是armeabi-v7ax86_64 和arm64-v8a(缺省值)。我们要使代码能够运行在x86的模拟器上,就需要设置该参数为x86_64。

执行过程如下:

-- The C compiler identification is Clang 12.0.1
-- The CXX compiler identification is Clang 12.0.1
-- Check for working C compiler: D:/Huawei/SDK/openharmony/9/native/llvm/bin/clang.exe
-- Check for working C compiler: D:/Huawei/SDK/openharmony/9/native/llvm/bin/clang.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: D:/Huawei/SDK/openharmony/9/native/llvm/bin/clang++.exe
-- Check for working CXX compiler: D:/Huawei/SDK/openharmony/9/native/llvm/bin/clang++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The ASM compiler identification is Clang
-- Found assembler: D:/Huawei/SDK/openharmony/9/native/llvm/bin/clang.exe
-- Configuring done
-- Generating done
-- Build files have been written to: D:/DevEcoStudioProjects/ohos_mqtt/ohos_Mqtt/src/main/cpp/out

正确生成makefile之后,可以执行如下命令进行编译:

D:\Huawei\SDK\OpenHarmony\9\native\build-tools\cmake\bin\cmake --build out

 最后编译成功,我们就得到了x86_64平台下的libmqttasync.so文件。

安装MQTT软件包

在本文写作的时候,ohpm/mqtt最新的版本是2.14,针对的是API12。如果直接在Terminal中使用下面的命令安装的是最新版本。

ohpm install @ohos/mqtt

如果在工程中直接使用最新的这个版本会报告如下错误:

> hvigor ERROR: Failed :entry:default@MergeProfile... 
> hvigor ERROR: The compatibleSdkVersion 9 cannot be smaller than version 12 declared in library [:ohos_Mqtt] 
          as the library might be using APIS not available in 9

所以最好的办法是使用老的版本,比如2.0.5-rc.0

ohpm install @ohos/mqtt@2.0.5-rc.0

使用2.06版本也可以,但是需要手工修改oh_modules/.ohpm/@ohos+mqtt@2.0.6/oh_modules/@ohos/mqtt/src/main/module.json文件中的minAPIVersion为9(默认是10)。

{
	"app": {
		"bundleName": "cn.openharmony.ohos_mqtt",
		"debug": true,
		"versionCode": 1000000,
		"versionName": "2.0.6-rc.0",
		"minAPIVersion": 9,
		"targetAPIVersion": 10,
		"apiReleaseType": "Beta2",
		"compileSdkVersion": "4.0.9.6",
		"compileSdkType": "OpenHarmony",
		"bundleType": "app"
	},
	"module": {
		"name": "ohos_Mqtt",
		"type": "har",
		"deviceTypes": [
			"default",
			"tablet"
		],
		"installationFree": false
	}
}

避免MQTT软件包自动升级

上面的操作虽然可以导入老版本的MQTT包,但是当三方包发布新版本后,点击同步工程,会出现默认更新安装的三方包版本情况。为了避免这种情况,手工修改oh-package.json5,将其中@ohos/mqtt一行版本号前面的“^"符号删除掉,这样保证安装固定版本的三方包。

{
  "name": "myapplication",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {
    "@ohos/mqtt": "2.0.6"
  },
  "devDependencies": {
    "@ohos/hypium": "1.0.6"
  },
  "dynamicDependencies": {}
}

设置libs

在DevEco Studio中,找到oh_modules/.ohpm/@ohos+mqtt@2.0.5/oh_modules/@ohos/mqtt/libs目录,在其下建立x86_64子目录,将libmqttasync.so和libc++_shared.so文件拷贝到其中。其中libc++_shared.so文件来自\Huawei\SDK\openharmony\9\native\llvm\lib\x86_64-linux-ohos\c++(具体路径取决于用户设置)。

客户端程序的编写

客户端程序的编写参考了参考文献中的第一个。

先建立MQTT.ets,内容如下:

import { MqttAsync, MqttClient, MqttPublishOptions, MqttResponse, MqttSubscribeOptions } from '@ohos/mqtt'

export class MQTT{
  private serverUrl: string = 'tcp://bemfa.com:9501'
  private clientId: string = 'xxxxxx'
  private userName: string = ''
  private password: string = ''
  public mqttAsyncClient: MqttClient = MqttAsync.createMqtt({
    url: this.serverUrl,
    clientId: this.clientId,
    persistenceType: 1,
  })

  private topic: string = "light002"

  connectMqtt() {
    this.mqttAsyncClient.connect({
      userName: this.userName,
      password: this.password,
    }).then(() => {
      this.mqttAsyncClient.isConnected()
        .then((data: boolean) => {
          console.log("连接状态: " + data)
        });
    }).catch(() => {
      console.warn('连接失败')
    })
  }

  subscribeMqtt() {
    let subscribeOption: MqttSubscribeOptions = {
      topic: this.topic,//主题名称
      qos: 0            //消息的服务质量设置
    }
    this.mqttAsyncClient.subscribe(subscribeOption)
      .then((data: MqttResponse) => {
        console.log("订阅成功 " + JSON.stringify(data));
      }).catch((err: MqttResponse) => {
      console.log("订阅失败" + JSON.stringify(err));
    })
  }

  messageArrived() {
    this.mqttAsyncClient.messageArrived((err, data) => {
      if (err) {
        console.error("接收消息时发生错误:", err);
      } else {
        console.log("接收到的消息:",JSON.stringify(data));
      }
    });
  }

  publish(message:string) {
    let publishOption: MqttPublishOptions = {
      topic: this.topic,               //主题名称
      qos: 0,                          //消息的服务质量设置
      payload: JSON.stringify(message),//发布的消息
    };

    this.mqttAsyncClient.publish(publishOption)
      .then((data: MqttResponse) => {
        console.log("推送成功" + JSON.stringify(data));
      })
      .catch((err: Error) => {
        console.log("推送失败" + JSON.stringify(err));
      });
  }

  disconnect() {
    this.mqttAsyncClient.disconnect()
      .then((data: MqttResponse) => {
        console.log("断开成功:" + JSON.stringify(data));
      })
      .catch((err: MqttResponse) => {
        console.log("断开失败:" + JSON.stringify(err));
      })
  }
}
export const mqtt = new MQTT();

程序中的设置是按照巴法云设置的, 巴法云不支持QoS2,所以将QoS改为0。

主程序的代码如下:

import promptAction from '@ohos.promptAction';
import { mqtt } from './MQTT';
 
@Entry
@Component
struct Index {
 
  @State message: string = 'Hello World'
 
  /**
   * In low-code mode, do not add anything to the build function, as it will be
   * overwritten by the content generated by the .visual file in the build phase.
   */
  build() {

  }
 
  buttonClick()
  {
    mqtt.connectMqtt()
  }
 
  buttonPublish()
  {
    mqtt.publish("Hello!")
  }
}

完整的程序可以从CSDN下载:在x86模拟器和鸿蒙API9如何使用MQTT模块ohos-mqtt的示例程序资源-CSDN文库icon-default.png?t=O83Ahttps://download.csdn.net/download/bit_mike/90091745。 

运行测试

接下来启动x86模拟器,然后在其上运行本工程即可。

先点击Connect按钮连接服务器,然后再点击Publish按钮就可以向服务器发布消息。

我们可以用Wireshark观测到整个通信过程:

结语

至此我们完成了最终的目标,这里面最核心的就是使用NDK编译了NAPI所使用库文件。整个过程虽然有点多,但是总体上看仍然是比较容易理解的。

参考文献

  • HarmonyOS实现MQTT_鸿蒙mqtt库-CSDN博客
  • docs/adapter_windows.md · OpenHarmony-SIG/tpc_c_cplusplus - Gitee.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934993.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

若依集成更好用的easyexcel

背景 若依使用的是apach poi并在此基础上进行封装apach poi的原生的api是很复杂的,若依简化了了此操作apach poi的上传速率和下载速率都是没有优化的,依赖于文件大小的限制在此前提下,如果没法满足客户的需求(超大型文件的上传&am…

我们来学mysql -- 探讨win安装方式(安装篇)

题记 书接上回,在我们来学mysql – 闲聊(安装篇)中,拿到安装包,当宝贝一样揣在怀里 然而,还没捂热乎,得粉丝秘报,U哥,上篇文章用了滞后的官方文档,哈哈哈…内心的小倔强&#xff0c…

[WiFi] WiFi安全加密WEP Vs WPA Vs WPA2 Vs WPA3整理

WiFi安全标准时间线 WEP(Wired Equivalent Privacy) WEP最早于1997年推出,是为了保护无线网络上的数据通信而设计的。当时,Wi-Fi技术还处于起步阶段,人们开始意识到需要一种安全协议来防止未经授权的访问和窃听。WEP被…

05 在 Linux 使用 AXI DMA

DMA简介 DMA 是一种采用硬件实现存储器与存储器之间或存储器与外设之间直接进行高速数据传输的技术,传输过程无需 CPU 参与(但是CPU需要提前配置传输规则),可以大大减轻 CPU 的负担。 DMA 存储传输的过程如下: CPU 向…

深入解析下oracle的number底层存储格式

oracle数据库中,number数据类型用来存储数值数据,它既可以存储负数数值,也可以存储正数数值。相对于其他类型数据,number格式的数据底层存储格式要复杂得多。今天我们就详细探究下oracle的number底层存储格式。 一、环境搭建 1.…

多速率信号处理

介绍 简单来说, 多速率信号处理,是指对同时存在两个以上数据速率的系统进行信号处理。多速率信号处理原理就是通过改变信号速率,以适应系统内部各个节点对信号速率的要求。这里的速率其实就是指采样率。 多速率技术已广泛应用于数字音频处理…

golang实现简单的redis服务

golang 手搓redis服务器仓库地址:实现思路: golang 手搓redis服务器 仓库地址: 仓库: https://github.com/dengjiayue/my-redis.git 实现思路: ● 协议: tcp通信 ● 数据包: 长度(4byte)方法(1byte)数据json ● 数据处理: 单线程map读写 ○ 依次处理待处理队列的请求(chan)…

ssd202d-badblock-坏块检测

这边文章讲述的是坏快检测功能 思路: 1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum = //坏块个数 lb_badoff = //坏块所在位置 2.第一次开机会根据lb_badnum是否存在判断,如果不存在则保存上…

Y3编辑器文档2:场景编辑

文章目录 一、操作区二、地图设置2.1 地图大小2.2 其它选项三、地形编辑3.1 地势3.2 地形3.3 通行(碰撞、通行和视野规则)3.4 植被四、物件放置4.1 单位4.1.1 单位的摆放与调整4.1.2 状态栏属性编辑4.2 装饰物摆放4.3 物品4.4 镜头4.4.1 镜头的基本参数4.4.2 镜头时间轴动画4…

windows将文件推给Android真机/实机

记录一下 因为以前只试过从真机实机中将文件推给windows 但是从windows只简单复制粘贴的话会一直报错。 1.电脑安装adb 2.手机开启开发者模式 usb调试 3.usb连接选择文件传输 4.推送命令adb push 文件路径 /sdcard/download 步骤1和2和3不作赘述,可以搜相关配置教程…

[机器学习] 监督学习之线性回归与逻辑回归

这里写目录标题 一、监督学习概述二、线性回归(一)模型表示(二)损失函数(三)梯度下降算法导入所需库生成模拟数据(可替换为真实数据)初始化参数并进行训练可视化损失函数随迭代次数的…

精准预测美国失业率和贫困率,谷歌人口动态基础模型PDFM已开源,可增强现有地理空间模型

疾病、经济危机、失业、灾害……人类世界长期以来被各种各样的问题「侵扰」,了解人口动态对于解决这类复杂的社会问题至关重要。 政府相关人员可以通过人口动态数据来模拟疾病的传播,预测房价和失业率,甚至预测经济危机。然而,在过…

E172 ASP.NET+SQL+C#+LW+图书管理系统的设计与实现 配置 源码 文档 全套资料

图书管理系统 1.项目摘要2. 系统的概述3.项目功能4.界面展示5.源码获取 1.项目摘要 摘 要 书籍是供人们获取并增长知识的主要途径,由于图书的种类较多,阅读者也较多,借阅量较大,且易出错,传统的图书借阅若还停留在手工…

aippt:AI 智能生成 PPT 的开源项目

aippt:AI 智能生成 PPT 的开源项目 在现代办公和学习中,PPT(PowerPoint Presentation)是一种非常重要的展示工具。然而,制作一份高质量的PPT往往需要花费大量的时间和精力。为了解决这一问题,aippt项目应运…

轮转数组

轮转数组 1、题目描述2、解答思路2.1、辅助数组2.2、原地反转 1、题目描述 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 2、解答思路 2.1、辅助数组 如果我们在原数组上通过覆盖元素会导致部分元素的丢失&#xff0c…

selenium学习:等待方式

隐式等待 1.针对查找元素设置最大的超时时间 2.可以全局性的设置 3.不满足时,提示no such element driver.implicitly_wait(5) #对查找元素最大的超时时间,如果超过最大等待时间后,没有找到元素,则会报错:no such #e…

一文说清flink从编码到部署上线

引言:目前flink的文章比较多,但一般都关注某一特定方面,很少有一个文章,从一个简单的例子入手,说清楚从编码、构建、部署全流程是怎么样的。所以编写本文,自己做个记录备查同时跟大家分享一下。本文以简单的…

ZUC256 Go Go Go!!!

文章目录 背景运行效果代码 背景 因业务需要使用ZUC算法,GitHub上又没有对ZUC256相对应的Go语言的实现。 吃水不忘挖井人,在这里感谢GmSSL及BouncyCastle两个强大的密码学库! 本ZUC256的编写,参考了这两个库及中科院软件院发布的…

图论【Lecode_HOT100】

文章目录 1.岛屿数量No.2002.腐烂的橘子No.9943.课程表No.2074.实现Trie(前缀树)No.208 1.岛屿数量No.200 class Solution {public int numIslands(char[][] grid) {if (grid null || grid.length 0) {return 0;}int numIslands 0;int rows grid.len…

快速将请求头构建成json结构

1.背景 有时候我们要爬虫(组包)请求一个资源数据,需要构建与原始请求一样的请求头,从浏览器复制过来的请求头,有很多,如果一个一个的配置成json有点慢,那么如何快速构建呢? 今天就使用正则表达式的方式实现 正则表达式实现快速将请求头构建成json结构 将冒号后边的换行符去掉…