/mqtt-nio

Non-blocking, event-driven Swift client for MQTT (3.1.1 and 5.0).

Primary LanguageSwiftMIT LicenseMIT

MQTTNIO

Non-blocking, event-driven Swift client for MQTT (5.0 and 3.1.1) build on SwiftNIO.

This library has support for WebSocket connections and TLS. It runs on all platforms Swift NIO runs on (e.g. macOS, iOS, Linux, etc.).

Tests Swift 5.7 Release

Installation

Use the SPM string to easily include the dependendency in your Package.swift file.

.package(url: "https://github.com/sroebert/mqtt-nio.git", from: "2.0.0")

Supported Platforms

MQTTNIO supports the following platforms:

  • Ubuntu 18.04+
  • macOS 10.9+, iOS 7+, tvOS 12+ or watchOS 6+

Dependencies

This package has four dependencies:

This package has no additional system dependencies.

Usage

Create Client and Connect

let client = MQTTClient(
    configuration: .init(
        target: .host("127.0.0.1", port: 1883)
    ),
    eventLoopGroupProvider: .createNew
)
client.connect()

The client automatically reconnects when failing to connect or when disconnected from the broker.

Connect to an MQTT 3.1.1 broker

let client = MQTTClient(
    configuration: .init(
        target: .host("127.0.0.1", port: 1883),
        protocolVersion: .version3_1_1
    ),
    eventLoopGroupProvider: .createNew
)
client.connect()

Connect using a URL

let client = MQTTClient(configuration: .init(url: URL(string: "mqtts://test.mosquitto.org")!))
client.connect()
let client = MQTTClient(configuration: .init(url: URL(string: "wss://test.mosquitto.org:8081")!))
client.connect()

Subscribe

client.subscribe(to: "some/topic")

Unsubscribe

client.unsubscribe(from: "some/topic")

Publish

client.publish("Hello World!", to: "some/topic", qos: .exactlyOnce)
client.publish("Hello World!", "some/topic")
client.publish("Hello World!", to: "some/topic", retain: true)

Receive callbacks to know when the client connects/disconnects and receives messages.

client.whenConnected { response in
    print("Connected, is session present: \(response.isSessionPresent)")
}
client.whenDisconnected { reason in
    print("Disconnected: \(reason)")
}
client.whenMessage { message in
    print("Received: \(message)")
}

For platforms where the Combine framework is available, it is also possible to subscribe to publishers.

let cancellable = client.connectPublisher
    .sink { response in
        print("Connected, is session present: \(response.isSessionPresent)")
    }
let cancellable = client.disconnectPublisher
    .sink { reason in
        print("Disconnected: \(reason)")
    }
let cancellable1 = client.messagePublisher
    .sink { message in
        print("Received: \(message)")
    }
let cancellable2 = client.messagePublisher(forTopic: "some/topic")
    .sink { message in
        print("Received: \(message)")
    }

async/await

On platforms where async await is supported, it is possible to use async functions on MQTTClient.

try await client.publish("Hello World!", "some/topic")
for await message in client.messages {
    print("Received: \(message)")
}

Unit Tests

To easily run the tests locally, first generate self signed certificates followed by running docker-compose to setup the needed MQTT broker containers.

./mosquitto/certs/generate.sh
docker compose up