我正在参与掘金创作者训练营第 4 期,点击了解活动详情,马上报名一起学习吧!
前言
上篇远程控制,Server与App网络通信初步调研已经描述了我们在技术选项上的一些思考,初步将MQTT作为了App与Server之间的网络通信协议。
立足这一点,我们就开始针对MQTT的调试。
iOS端的MQTT框架选型
首先既然做iOS开发,我们首先需要选择合适的MQTT框架,便于集成和调试。
这当然比较简单,直接上GitHub上进行一番搜索即可,当然这次的搜索稍微有点技巧:
在网址中我们添加了l=Swift
表示编程语言是Swift,这样搜索下来,一般排在前面的就是我们需要使用的框架:
基本上和我想的差不多,一般情况下iOS在某些第三库的选择上甚少,基本上没有可以选择的余地,这个有1.3k Stars的CocoaMQTT基本上是我们唯一的选择。
当然,我也试了一下Objective-C的框架,基本上也只有一家的star上了k,可以使用:
考虑到我们主要使用Swift进行开发,所以这次大方向上面,我们会使用CocoaMQTT。
MQTTX调试端工具使用
一般情况下,我们会马上集成CocoaMQTT到App里面进行调试即可,不过MQTT的调试有点特殊,我们需要在电脑上安装MQTTX作为一个调试工具使用。
你可以假装认为MQTTX调试端是我们Device端,它用于将Device的上报信息发送给Server,然后Server端接到Device的消息后,再发送给App端。
有关与MQTTX这款软件,大家可以看看这里,它有专门的中文介绍页面。
如果想要直接下载,也很方便:
这里简单说明一下这个软件使用:
有关与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,等等。
我们创建好一个后,连接即可:
接着我们添加订阅,添加订阅必须在连接后才能操作,这个订阅就是上面所说的Topic,我们这里订阅一个/go
的话题:
到此,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上面显示:
注意上面那个season是我上次调试的记录,还保留在。
接着我们可以在MQTTX上发一条消息给App:
我们看看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的集成,在大的方向没有太多问题,更多的细节,需要在实战一番淬炼。
最近武汉有疫情,希望大家保重身体,后续几个月,工作会异常忙碌,估计无法摸鱼更文了,哈哈。