如何在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所使用库文件。整个过程虽然有点多,但是总体上看仍然是比较容易理解的。

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神一样的老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值