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.

Background Modes

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.


EMQX
336 声望436 粉丝

EMQ(杭州映云科技有限公司)是一家开源物联网数据基础设施软件供应商,交付全球领先的开源 MQTT 消息服务器和流处理数据库,提供基于云原生+边缘计算技术的一站式解决方案,实现企业云边端实时数据连接、移动、...