In August 2017, the OASIS MQTT Technical Committee officially released the MQTT 5.0 draft for Public Review. In 2018, MQTT 5.0 was officially released, but until now, there is still no client SDK that fully supports MQTT 5.0 in the Apple ecosystem.
CocoaMQTT is the MQTT client SDK provided by the EMQ team for iOS developers. It is currently widely used by iOS developers.
In order to make up for the gap in the support of MQTT 5.0 in the Apple ecosystem, the EMQ team recently officially released the new version of v2.0 1619dd4f23c849. CocoaMQTT v2.0 supports MQTT 5.0, is compatible with version 3.1.1, and supports iOS, tvOS and OSX operating systems. Users can now connect iOS system devices to the MQTT 5.0 cloud service through CocoaMQTT, and enjoy the powerful features brought by MQTT 5.0.
CocoaMQTT is developed in Swift language instead of Objective-C. This is because Swift is a type-safe language with richer support for protocols. With extensions, generics, associated types, etc., protocol-oriented programming can be implemented, which greatly improves the flexibility of the code.
In addition, at the WWDC 2021 conference, Apple announced a major update of the concurrency model in the Swift language: the Actor concurrency model implemented by the compiler, and the new Actor reference type to help developers avoid data competition issues.
Therefore, we believe that in MQTT related I/O intensive concurrent applications, Swift's performance will be more worth looking forward to compared to Objective-C.
MQTT 5.0 vs MQTT 3.1.1
MQTT 3.1.1 still has many imperfections, such as the failure to notify the opposite end when the connection is abnormally disconnected. MQTT 5.0 has made many changes on the basis of MQTT 3.1.1, but it is not backward compatible.
Version 5.0 of the MQTT protocol adds new functions such as session/message delay, reason codes, topic aliases, in-flight flow control, user attributes, shared subscriptions, and AUTH messages to enhance authentication security. Among them, the reason code and the user attribute Property
field enable MQTT 5.0 to carry more context information, thereby solving the problem that is difficult to handle in the 3.1.1 version due to the incomplete protocol.
The main functional advantages of MQTT 5.0 are:
- Further support for larger scale scalable systems
- More detailed error reporting and handling mechanism
- Standardized operation of common modes such as capacity exploration and request response
- Extensible User Property (User Property)
- Improve performance and support small clients
- Session persistence and message timeout settings
- Added support for Req/Rsp message mode
Use of CocoaMQTT client
This article will use the free public MQTT server provided by EMQ to introduce the CocoaMQTT function, which is based on the MQTT cloud service EMQ X Cloud.
Server access information is as follows:
- Broker: broker-cn.emqx.io
- TCP Port: 1883
- Websocket Port: 8083
- TCP/TLS port: 8883
- Websocket/TLS port: 8084
Connect to MQTT service
We see that MQTT 5.0 adds many attributes, among which the Property
field allows users to fulfill their requirements in more detail according to their own situation.
///MQTT 5.0
let clientID = "CocoaMQTT-" + String(ProcessInfo().processIdentifier)
let mqtt5 = CocoaMQTT5(clientID: clientID, host: "broker-cn.emqx.io", port: 1883)
let connectProperties = MqttConnectProperties()
connectProperties.topicAliasMaximum = 0
connectProperties.sessionExpiryInterval = 0
connectProperties.receiveMaximum = 100
connectProperties.maximumPacketSize = 500
mqtt5.connectProperties = connectProperties
mqtt5.username = "test"
mqtt5.password = "public"
mqtt5.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout")
mqtt5.keepAlive = 60
mqtt5.delegate = self
mqtt5.connect()
///MQTT 3.1.1
let clientID = "CocoaMQTT-" + String(ProcessInfo().processIdentifier)
let mqtt = CocoaMQTT(clientID: clientID, host: "broker-cn.emqx.io", port: 1883)
mqtt.username = "test"
mqtt.password = "public"
mqtt.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout")
mqtt.keepAlive = 60
mqtt.delegate = self
mqtt.connect()
Subscribe to topics
MQTT 5.0 adds subscription options and other operations on MQTT 3.1.1.
///MQTT 5.0
mqtt5.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1)
//or
//let subscriptions : [MqttSubscription] = [MqttSubscription(topic: "chat/room/animals/client/+"),MqttSubscription(topic: "chat/room/foods/client/+"),MqttSubscription(topic: "chat/room/trees/client/+")]
//mqtt.subscribe(subscriptions)
///MQTT 3.1.1
mqtt.subscribe("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1)
//or
//let subscriptions : [(String, CocoaMQTTQoS)] = [("chat/room/animals/client/+", qos: CocoaMQTTQoS.qos1),("chat/room/foods/client/+", qos: CocoaMQTTQoS.qos1),("chat/room/trees/client/+", qos: CocoaMQTTQoS.qos1)]
//mqtt.subscribe(subscriptions)
make an announcement
///MQTT 5.0
mqtt5!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1, DUP: false, retained: false, properties: publishProperties)
///MQTT 3.1.1
mqtt!.publish("chat/room/animals/client/" + animal!, withString: message!, qos: .qos1)
Auto reconnect
MQTT is a protocol based on TCP long connections. In actual use scenarios, connection interruption due to network failures or signal problems is a common problem. Many developers hope that the SDK can provide a convenient way to automatically reconnect.
///MQTT 5.0
mqtt5!.autoReconnect = true
///MQTT 3.1.1
mqtt!.autoReconnect = true
Single and two-way SSL connection
///MQTT 5.0
mqtt5!.enableSSL = true
///MQTT 3.1.1
mqtt!.enableSSL = true
let clientCertArray = getClientCertFromP12File(certName: "client-keycert", certPassword: "MySecretPassword")
var sslSettings: [String: NSObject] = [:]
sslSettings[kCFStreamSSLCertificates as String] = clientCertArray
///MQTT 5.0
mqtt5!.sslSettings = sslSettings
///MQTT 3.1.1
mqtt!.sslSettings = sslSettings
If you need a .p12 file, you can use the following statement to generate it in the terminal
1openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-key.pem -out client.p12
Set hold message and will message
Compared with MQTT 3.1.1, MQTT 5.0 has more property settings for users to use.
///MQTT 5.0
let lastWillMessage = CocoaMQTTMessage(topic: "/chat/room/animals/client/Sheep", string: "dieout")
lastWillMessage.retained = true
lastWillMessage.qos = .qos1
mqtt5!.willMessage = lastWillMessage
///MQTT 3.1.1
mqtt!.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")
AUTH message
MQTT simply passing CONNECT
may not be able to provide enough information for Server to perform identity authentication, so MQTT 5.0 adds this feature. Used to strengthen authentication between the client and the server.
let authProperties = MqttAuthProperties()
mqtt5!.auth(reasonCode: CocoaMQTTAUTHReasonCode.continueAuthentication, authProperties: authProperties)
iOS app running in the background
It is recommended to use the "Background fetch" mode or the "Background processing" mode added in IOS 13.
If you use beginBackgroundTaskWithName
and endBackgroundTask
, you can keep the APP running in the background for 30 seconds.
Summarize
At this point, we have completed the use of the CocoaMQTT client to connect to the public MQTT server, and realized the connection between the client and the MQTT server, message publishing and subscription.
For the complete code of the project, please see https://github.com/emqx/CocoaMQTT/tree/master/Example.
EMQ is committed to helping users easily and conveniently use MQTT to develop Internet of Things business. Our series of client SDKs are under continuous development, so stay tuned.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。