远程控制,MQTT调试

我正在参与掘金创作者训练营第 4 期,点击了解活动详情,马上报名一起学习吧!

前言

上篇远程控制,Server与App网络通信初步调研已经描述了我们在技术选项上的一些思考,初步将MQTT作为了App与Server之间的网络通信协议。

立足这一点,我们就开始针对MQTT的调试。

iOS端的MQTT框架选型

首先既然做iOS开发,我们首先需要选择合适的MQTT框架,便于集成和调试。

这当然比较简单,直接上GitHub上进行一番搜索即可,当然这次的搜索稍微有点技巧:

github.com/search?l=Sw…

在网址中我们添加了l=Swift表示编程语言是Swift,这样搜索下来,一般排在前面的就是我们需要使用的框架:

image.png

基本上和我想的差不多,一般情况下iOS在某些第三库的选择上甚少,基本上没有可以选择的余地,这个有1.3k Stars的CocoaMQTT基本上是我们唯一的选择。

当然,我也试了一下Objective-C的框架,基本上也只有一家的star上了k,可以使用:

image.png

考虑到我们主要使用Swift进行开发,所以这次大方向上面,我们会使用CocoaMQTT

MQTTX调试端工具使用

一般情况下,我们会马上集成CocoaMQTT到App里面进行调试即可,不过MQTT的调试有点特殊,我们需要在电脑上安装MQTTX作为一个调试工具使用。

ee9738eeff11754737876ff23416d295的副本.jpeg

你可以假装认为MQTTX调试端是我们Device端,它用于将Device的上报信息发送给Server,然后Server端接到Device的消息后,再发送给App端。

有关与MQTTX这款软件,大家可以看看这里,它有专门的中文介绍页面。

github.com/emqx/MQTTX

如果想要直接下载,也很方便:

mqttx.app/

这里简单说明一下这个软件使用:

image.png

image.png

有关与MQTT的调试,我们只需要记住三个配置的要素即可:

  • Topic,话题,这个地方就很像“物以类聚人以群分”的道理,只有App和Device都在同一话题下面,App才能收到相关的消息。

  • QoS的类型,细分为0,1,2:

    • QoS0,At most once,至多一次;
    • QoS1,At least once,至少一次;
    • QoS2,Exactly once,确保只有一次。

    大家有兴趣的可以看看这篇文章,说的比较详细: MQTT系列 | MQTT的QoS介绍

    我们只需要记住,这玩意其实就是目前就是通信质量的类型,不太影响我们的调试。

  • Payload,负载,也就是我们发送的消息,和我们开发的时候大同小异,可以是一个JSON,也可以是一个String,等等。

我们创建好一个后,连接即可:

image.png

接着我们添加订阅,添加订阅必须在连接后才能操作,这个订阅就是上面所说的Topic,我们这里订阅一个/go的话题:

image.png

到此,MQTTX的基本配置完成。

下面我们来说说App端的配置。

App端集成CocoaMQTT,并调试

其实,GitHub上面CocoaMQTT的文档和Demo,已经展示的比较详细了,这里稍微搬运一下,添加一点注释

let clientID = "season"

/// 初始化CocoaMQTT实例,入参clientID,这里的clientID需要和MQTTX的设置的不同,host port与MQTTX的设置保持一致
mqtt = CocoaMQTT(clientID: clientID, host: "", port: 0000)

/// 设置用户名
mqtt!.username = ""

/// 设置密码
mqtt!.password = ""

/// App端的遗嘱消息
mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")

/// 设置keepAlive
mqtt!.keepAlive = 60

/// 设置代理
mqtt!.delegate = self

/// 连接操作
let _ = mqtt!.connect()
复制代码

上面的基本操作完成后,我们主要看看mqtt的代理回调,代理有很多个方法,但是基本上我们先瞅瞅最重关心的几个方法:

extension ViewController: CocoaMQTTDelegate {
    
    /// 连接成功的回调,在ack为.accept时,才能订阅Topic,这里我订阅了/will话题,我在这里publish了一条消息给MQTTX端,并且Topic为/go
    func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {

        if ack == .accept {
            /// 订阅/will话题
            mqtt.subscribe("/will", qos: CocoaMQTTQoS.qos0)
            /// 发出带有/go话题的消息
            mqtt.publish("/go", withString: "iOS App Message", qos: .qos0, retained: true)

        }

    }

    /// App端已经publish的信息
    func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {

        print("message: \(message.string.description), id: \(id)")

    }

    /// App端已经收到的消息
    func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 ) {

        print("message: \(message.string.description), id: \(id)")
    }

    /// App端已经订阅的Topic的话题
    func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {

    }

}
复制代码

我们可以简单看看这样连接成功后,打印的日志:

welcome to MQTT Optional("3.1.1")  Optional("Sheep")

[TRACE] [didStateChangeTo]: new state: connecting

[TRACE] [didConnectAck]: ack: accept

[TRACE] [didStateChangeTo]: new state: connected

[TRACE] [didPublishMessage]: message: iOS App Message, id: 0

[TRACE] [didSubscribeTopics]: subscribed: {

    "/will" = 0;

}, failed: []

复制代码

我订阅了话题/will,并向MQTTX端发了一条iOS App Message的消息,我们去MQTTX上面显示:

image.png

注意上面那个season是我上次调试的记录,还保留在。

接着我们可以在MQTTX上发一条消息给App:

image.png

我们看看App端是不是收到消息了:

[TRACE] [didReceiveMessage]: message: {

  "message": "MQTT Message"

}, id: 0
复制代码

到此,Device与App的相互通信基本上完成了。这里我们基本上忽略了Server,只是做了Server在MQTTX与App的配置,但是Server的搭建与配置非常重要,不然,我这啥通信也调试不出来。

总结

到此为止,远程控制,Server与App网络通信初步调研和MQTT调试基本完成了。

其实MQTT调试还有非常多的细节,比如SSL,QoS的设置,以及本地证书的设置,MQTT3与MQTT5版本的差异等等。

不过整体而言,MQTTX的配置,还是App的集成,在大的方向没有太多问题,更多的细节,需要在实战一番淬炼。

最近武汉有疫情,希望大家保重身体,后续几个月,工作会异常忙碌,估计无法摸鱼更文了,哈哈。

猜你喜欢

转载自juejin.im/post/7069558573927235614