- MQTT(上报位置、订阅成员、收到消息更新成员列表对应信息)

This commit is contained in:
linshujie 2026-06-15 18:38:15 +08:00
parent d5296061c3
commit 67dc7baa02
125 changed files with 40365 additions and 12032 deletions

View File

@ -50,6 +50,7 @@ target 'QuickLocation' do
#第三方SDk
pod 'GYSDK' #个推一键登录
pod 'OpenIMSDK' #OpenIM
pod 'CocoaMQTT' #MQTT
#支付宝
pod 'AlipaySDK-iOS'

View File

@ -11,6 +11,10 @@ PODS:
- CocoaLumberjack/Core (3.9.1)
- CocoaLumberjack/Swift (3.9.1):
- CocoaLumberjack/Core
- CocoaMQTT (2.2.5):
- CocoaMQTT/Core (= 2.2.5)
- CocoaMQTT/Core (2.2.5):
- MqttCocoaAsyncSocket (~> 1.0.8)
- Differentiator (5.0.0)
- GTCommonSDK (3.2.3.0):
- ZXSDK
@ -89,6 +93,7 @@ PODS:
- Moya/Core (= 15.0.0)
- Moya/Core (15.0.0):
- Alamofire (~> 5.0)
- MqttCocoaAsyncSocket (1.0.8)
- ObjectMapper (4.4.2)
- "OpenIMSDK (3.8.3+hotfix.3.1)":
- MJExtension
@ -174,6 +179,7 @@ DEPENDENCIES:
- AMapLocation
- AMapSearch
- CocoaLumberjack/Swift
- CocoaMQTT
- GYSDK
- HXPHPicker
- IQKeyboardManagerSwift
@ -215,6 +221,7 @@ SPEC REPOS:
- AMapLocation
- AMapSearch
- CocoaLumberjack
- CocoaMQTT
- Differentiator
- GTCommonSDK
- GYSDK
@ -236,6 +243,7 @@ SPEC REPOS:
- MJExtension
- MJRefresh
- Moya
- MqttCocoaAsyncSocket
- ObjectMapper
- OpenIMSDK
- OpenIMSDKCore
@ -277,6 +285,7 @@ SPEC CHECKSUMS:
AMapLocation: 6e44f50b044dc54c6b3dcb1dee5ffd6de2689e41
AMapSearch: 29224a399b56b17da1540e4312fc4d9dc37342bb
CocoaLumberjack: e4ba3b414dfca8c1916c6303d37f63b3a95134c6
CocoaMQTT: 1e2fa493d57045d66fb1eba2bb5ffb8d77039c60
Differentiator: e8497ceab83c1b10ca233716d547b9af21b9344d
GTCommonSDK: 238c6735add91e654f8564638854686ee3dcb4ac
GYSDK: db5f4b3aae8df06201be5e786076211ec11791be
@ -299,6 +308,7 @@ SPEC CHECKSUMS:
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
MqttCocoaAsyncSocket: 77d3b74f76228dd5a05d1f9526eab101d415b30c
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
@ -323,6 +333,6 @@ SPEC CHECKSUMS:
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
PODFILE CHECKSUM: 6ba8ada83ccc565c9bdcc418e9a936818640882c
PODFILE CHECKSUM: 861114200722c29adba98535aef6b0494d123b44
COCOAPODS: 1.16.2

2
Pods/CocoaMQTT/LICENSE generated Normal file
View File

@ -0,0 +1,2 @@
This project is dual licensed under the Eclipse Public License 1.0 and the
Eclipse Distribution License 1.0 as described in the epl-v10 and edl-v10 files.

350
Pods/CocoaMQTT/README.md generated Normal file
View File

@ -0,0 +1,350 @@
# CocoaMQTT
![PodVersion](https://img.shields.io/cocoapods/v/CocoaMQTT5.svg)
![Platforms](https://img.shields.io/cocoapods/p/CocoaMQTT5.svg)
![License](https://img.shields.io/cocoapods/l/BadgeSwift.svg?style=flat)
![Swift version](https://img.shields.io/badge/swift-5-orange.svg)
MQTT v3.1.1 and v5.0 client library for iOS/macOS/tvOS written with Swift 5
## Build
Build with Xcode 11.1 / Swift 5.1
IOS Target: 12.0 or above
OSX Target: 10.13 or above
TVOS Target: 10.0 or above
## xcode 14.3 issue:
```ruby
File not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a
```
If you encounter the issue, Please update your project minimum depolyments to 11.0
## Installation
### Swift Package Manager
To integrate CocoaMQTT into your Xcode project using [Swift Package Manager](https://swift.org/package-manager/), follow these steps:
1. Open your project in Xcode.
2. Go to `File` > `Swift Packages` > `Add Package Dependency`.
3. Enter the repository URL: `https://github.com/emqx/CocoaMQTT.git`.
4. Choose the latest version or specify a version range.
5. Add the package to your target.
At last, import "CocoaMQTT" to your project:
```swift
import CocoaMQTT
```
### CocoaPods
To integrate CocoaMQTT into your Xcode project using [CocoaPods](http://cocoapods.org), you need to modify you `Podfile` like the followings:
```ruby
use_frameworks!
target 'Example' do
pod 'CocoaMQTT'
end
```
Then, run the following command:
```bash
$ pod install
```
At last, import "CocoaMQTT" to your project:
```swift
import CocoaMQTT
```
## Usage
Create a client to connect [MQTT broker](https://www.emqx.com/en/mqtt/public-mqtt5-broker):
```swift
///MQTT 5.0
let clientID = "CocoaMQTT-" + String(ProcessInfo().processIdentifier)
let mqtt5 = CocoaMQTT5(clientID: clientID, host: "broker.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 = CocoaMQTTMessage(topic: "/will", string: "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.emqx.io", port: 1883)
mqtt.username = "test"
mqtt.password = "public"
mqtt.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")
mqtt.keepAlive = 60
mqtt.delegate = self
mqtt.connect()
```
Now you can use closures instead of `CocoaMQTTDelegate`:
```swift
mqtt.didReceiveMessage = { mqtt, message, id in
print("Message received in topic \(message.topic) with payload \(message.string!)")
}
```
## SSL Secure
#### One-way certification
No certificate is required locally.
If you want to trust all untrust CA certificates, you can do this:
```swift
mqtt.allowUntrustCACertificate = true
```
#### Two-way certification
Need a .p12 file which is generated by a public key file and a private key file. You can generate the p12 file in the terminal:
```
openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-key.pem -out client.p12
```
Note: Please use openssl version 1.1 (e.g. `brew install openssl@1.1`), otherwise you may not be able to import the generated .p12 file to the system correctly.
## MQTT over Websocket
In the 1.3.0, The CocoaMQTT has supported to connect to MQTT Broker by Websocket.
If you integrated by **Swift Package Manager**, follow these steps:
1. Open your project in Xcode.
2. Go to `File` > `Swift Packages` > `Add Package Dependency`.
3. Enter the repository URL: `https://github.com/emqx/CocoaMQTT.git`.
4. Choose the latest version or specify a version range.
5. Add the package to your target.
At last, import "CocoaMQTT" and "Starscream" to your project:
```swift
import CocoaMQTT
import CocoaMQTTWebSocket
import Starscream
```
If you integrated by **CocoaPods**, you need to modify you `Podfile` like the followings and execute `pod install` again:
```ruby
use_frameworks!
target 'Example' do
pod 'CocoaMQTT/WebSockets'
end
```
If you're using CocoaMQTT in a project with only a `.podspec` and no `Podfile`, e.g. in a module for React Native, add this line to your `.podspec`:
```ruby
Pod::Spec.new do |s|
...
s.dependency "Starscream"
end
```
Then, Create a MQTT instance over Websocket:
```swift
///MQTT 5.0
let websocket = CocoaMQTTWebSocket(uri: "/mqtt")
let mqtt5 = CocoaMQTT5(clientID: clientID, host: host, port: 8083, socket: websocket)
let connectProperties = MqttConnectProperties()
connectProperties.topicAliasMaximum = 0
// ...
mqtt5.connectProperties = connectProperties
// ...
_ = mqtt5.connect()
///MQTT 3.1.1
let websocket = CocoaMQTTWebSocket(uri: "/mqtt")
let mqtt = CocoaMQTT(clientID: clientID, host: host, port: 8083, socket: websocket)
// ...
_ = mqtt.connect()
```
If you want to add additional custom header to the connection, you can use the following:
```swift
let websocket = CocoaMQTTWebSocket(uri: "/mqtt")
websocket.headers = [
"x-api-key": "value"
]
websocket.enableSSL = true
let mqtt = CocoaMQTT(clientID: clientID, host: host, port: 8083, socket: websocket)
// ...
_ = mqtt.connect()
```
If you want to connect using WebSocket Secure (wss), you can use the following example:
```swift
import CocoaMQTT
import CocoaMQTTWebSocket
import Starscream
class WebSocketManager {
private var mqttClient: CocoaMQTT?
var message: String = ""
var token: String = ""
func setupMQTTClient(with token: String) {
let socket = CocoaMQTTWebSocket(uri: "/mqtt")
socket.enableSSL = true
mqttClient = CocoaMQTT(clientID: token, host: "host", port: 443, socket: socket)
mqttClient?.delegate = self
}
func connect() {
guard let mqttClient = mqttClient else { return }
mqttClient.connect()
}
}
extension WebSocketManager: CocoaMQTTDelegate {
func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
// Implement your custom SSL validation logic here.
// For example, you might want to always trust the certificate for testing purposes:
completionHandler(true)
}
func mqtt(_ mqtt: CocoaMQTT, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if let serverTrust = challenge.protectionSpace.serverTrust {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
return
}
}
completionHandler(.performDefaultHandling, nil)
}
func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("\(#function), \n result:- \(challenge.debugDescription)")
}
func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
print("Published message with ID: \(id)")
}
func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) {
print("Unsubscribed from topics: \(topics)")
}
func mqttDidPing(_ mqtt: CocoaMQTT) {
print("MQTT did ping")
}
func mqttDidReceivePong(_ mqtt: CocoaMQTT) {
print("MQTT did receive pong")
}
func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: (any Error)?) {
print("Disconnected from MQTT broker with error: \(String(describing: err))")
}
func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
print("Connected to MQTT broker with acknowledgment: \(ack)")
}
func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
if let messageString = message.string {
DispatchQueue.main.async {
self.message = messageString
}
print("Received message: \(messageString) on topic: \(message.topic)")
}
}
func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
print("Published message: \(message.string ?? "") with ID: \(id)")
}
func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {
print("Subscribed to topics: \(success), failed to subscribe to: \(failed)")
}
func mqtt(_ mqtt: CocoaMQTT, didDisconnectWithError err: Error?) {
print("Disconnected from MQTT broker with error: \(String(describing: err))")
}
}
```
## Example App
You can follow the Example App to learn how to use it. But we need to make the Example App works first:
```bash
$ cd Examples
```
Then, open the `Example.xcodeproj` by Xcode and start it!
## Dependencies
These third-party functions are used:
~~[GCDAsyncSocket](https://github.com/robbiehanson/CocoaAsyncSocket)~~
* [MqttCocoaAsyncSocket](https://github.com/leeway1208/MqttCocoaAsyncSocket)
* [Starscream](https://github.com/daltoniam/Starscream)
## LICENSE
MIT License (see `LICENSE`)
## Contributors
* [@andypiper](https://github.com/andypiper)
* [@turtleDeng](https://github.com/turtleDeng)
* [@jan-bednar](https://github.com/jan-bednar)
* [@jmiltner](https://github.com/jmiltner)
* [@manucheri](https://github.com/manucheri)
* [@Cyrus Ingraham](https://github.com/cyrusingraham)
## Author
- Feng Lee <feng@emqx.io>
- CrazyWisdom <zh.whong@gmail.com>
- Alex Yu <alexyu.dc@gmail.com>
- Leeway <leeway1208@gmail.com>
## Twitter
https://twitter.com/EMQTech

842
Pods/CocoaMQTT/Source/CocoaMQTT.swift generated Normal file
View File

@ -0,0 +1,842 @@
//
// CocoaMQTT.swift
// CocoaMQTT
//
// Created by Feng Lee<feng@eqmtt.io> on 14/8/3.
// Copyright (c) 2015 emqx.io. All rights reserved.
//
import Foundation
import MqttCocoaAsyncSocket
/**
* Conn Ack
*/
@objc public enum CocoaMQTTConnAck: UInt8, CustomStringConvertible {
case accept = 0
case unacceptableProtocolVersion
case identifierRejected
case serverUnavailable
case badUsernameOrPassword
case notAuthorized
case reserved
public init(byte: UInt8) {
switch byte {
case CocoaMQTTConnAck.accept.rawValue..<CocoaMQTTConnAck.reserved.rawValue:
self.init(rawValue: byte)!
default:
self = .reserved
}
}
public var description: String {
switch self {
case .accept: return "accept"
case .unacceptableProtocolVersion: return "unacceptableProtocolVersion"
case .identifierRejected: return "identifierRejected"
case .serverUnavailable: return "serverUnavailable"
case .badUsernameOrPassword: return "badUsernameOrPassword"
case .notAuthorized: return "notAuthorized"
case .reserved: return "reserved"
}
}
}
/// CocoaMQTT Delegate
@objc public protocol CocoaMQTTDelegate {
///
func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck)
///
func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16)
///
func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16)
///
func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 )
///
func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String])
///
func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String])
///
func mqttDidPing(_ mqtt: CocoaMQTT)
///
func mqttDidReceivePong(_ mqtt: CocoaMQTT)
///
func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?)
/// Manually validate SSL/TLS server certificate.
///
/// This method will be called if enable `allowUntrustCACertificate`
@objc optional func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void)
@objc optional func mqttUrlSession(_ mqtt: CocoaMQTT, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
///
@objc optional func mqtt(_ mqtt: CocoaMQTT, didPublishComplete id: UInt16)
///
@objc optional func mqtt(_ mqtt: CocoaMQTT, didStateChangeTo state: CocoaMQTTConnState)
/// Called when auto-reconnect schedules a reconnect attempt after an unexpected disconnect.
@objc optional func mqtt(_ mqtt: CocoaMQTT, didScheduleReconnect attemptCount: UInt, after interval: UInt16)
}
/// set mqtt version to 3.1.1
public func setMqtt3Version() {
if let storage = CocoaMQTTStorage() {
storage.setMQTTVersion("3.1.1")
}
}
/**
* Blueprint of the MQTT Client
*/
protocol CocoaMQTTClient {
/* Basic Properties */
var host: String { get set }
var port: UInt16 { get set }
var clientID: String { get }
var username: String? {get set}
var password: String? {get set}
var cleanSession: Bool {get set}
var keepAlive: UInt16 {get set}
var willMessage: CocoaMQTTMessage? {get set}
/* Basic Properties */
/* CONNNEC/DISCONNECT */
func connect() -> Bool
func connect(timeout: TimeInterval) -> Bool
func disconnect()
func ping()
/* CONNNEC/DISCONNECT */
/* PUBLISH/SUBSCRIBE */
func subscribe(_ topic: String, qos: CocoaMQTTQoS)
func subscribe(_ topics: [(String, CocoaMQTTQoS)])
func unsubscribe(_ topic: String)
func unsubscribe(_ topics: [String])
func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS, retained: Bool) -> Int
func publish(_ message: CocoaMQTTMessage) -> Int
/* PUBLISH/SUBSCRIBE */
}
/// MQTT Client
///
/// - Note: MGCDAsyncSocket need delegate to extend NSObject
public class CocoaMQTT: NSObject, CocoaMQTTClient {
public weak var delegate: CocoaMQTTDelegate?
private var version = "3.1.1"
public var host = "localhost"
public var port: UInt16 = 1883
public var clientID: String
public var username: String?
public var password: String?
/// Clean Session flag. Default is true
///
/// - TODO: What's behavior each Clean Session flags???
public var cleanSession = true
/// Setup a **Last Will Message** to client before connecting to broker
public var willMessage: CocoaMQTTMessage?
/// Enable backgounding socket if running on iOS platform. Default is true
///
/// - Note:
public var backgroundOnSocket: Bool {
get { return (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket ?? true }
set { (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket = newValue }
}
/// Delegate Executed queue. Default is `DispatchQueue.main`
///
/// The delegate/closure callback function will be committed asynchronously to it
public var delegateQueue = DispatchQueue.main
public var connState = CocoaMQTTConnState.disconnected {
didSet {
__delegate_queue {
self.delegate?.mqtt?(self, didStateChangeTo: self.connState)
self.didChangeState(self, self.connState)
}
}
}
// deliver
private var deliver = CocoaMQTTDeliver()
/// Re-deliver the un-acked messages
public var deliverTimeout: Double {
get { return deliver.retryTimeInterval }
set { deliver.retryTimeInterval = newValue }
}
/// Message queue size. default 1000
///
/// The new publishing messages of Qos1/Qos2 will be drop, if the queue is full
public var messageQueueSize: UInt {
get { return deliver.mqueueSize }
set { deliver.mqueueSize = newValue }
}
/// In-flight window size. default 10
public var inflightWindowSize: UInt {
get { return deliver.inflightWindowSize }
set { deliver.inflightWindowSize = newValue }
}
/// Keep alive time interval
public var keepAlive: UInt16 = 60
private var aliveTimer: CocoaMQTTTimer?
/// Enable auto-reconnect mechanism
public var autoReconnect = false
/// Reconnect time interval
///
/// - note: This value will be increased with `autoReconnectTimeInterval *= 2`
/// if reconnect failed
public var autoReconnectTimeInterval: UInt16 = 1 // starts from 1 second
/// Maximum auto reconnect time interval
///
/// The timer starts from `autoReconnectTimeInterval` second and grows exponentially until this value
/// After that, it uses this value for subsequent requests.
public var maxAutoReconnectTimeInterval: UInt16 = 128 // 128 seconds
/// Auto-reconnect backoff interval in seconds for the current reconnect cycle.
///
/// This value is advanced for the next reconnect attempt while auto-reconnect is active,
/// and resets to `0` when auto-reconnect is inactive.
public private(set) var reconnectTimeInterval: UInt16 = 0
/// Number of reconnect attempts scheduled in the current auto-reconnect cycle.
///
/// The value resets to `0` after a successful connection or expected disconnect.
public private(set) var reconnectAttemptCount: UInt = 0
private var autoReconnTimer: CocoaMQTTTimer?
private var is_internal_disconnected = false
/// Console log level
public var logLevel: CocoaMQTTLoggerLevel {
get {
return CocoaMQTTLogger.logger.minLevel
}
set {
CocoaMQTTLogger.logger.minLevel = newValue
}
}
/// Enable SSL connection
public var enableSSL: Bool {
get { return self.socket.enableSSL }
set { socket.enableSSL = newValue }
}
///
public var sslSettings: [String: NSObject]? {
get { return (self.socket as? CocoaMQTTSocket)?.sslSettings ?? nil }
set { (self.socket as? CocoaMQTTSocket)?.sslSettings = newValue }
}
/// Allow self-signed ca certificate.
///
/// Default is false
public var allowUntrustCACertificate: Bool {
get { return (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate ?? false }
set { (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate = newValue }
}
/// The subscribed topics in current communication
///
/// Keeping this dictionary-typed preserves the public API while the backing store remains thread-safe.
public var subscriptions: [String: CocoaMQTTQoS] {
get { subscriptionsStorage.snapshot() }
set { subscriptionsStorage.replace(with: newValue) }
}
private var subscriptionsStorage = ThreadSafeDictionary<String, CocoaMQTTQoS>(label: "subscriptions")
fileprivate var subscriptionsWaitingAck = ThreadSafeDictionary<UInt16, [(String, CocoaMQTTQoS)]>(label: "subscriptionsWaitingAck")
fileprivate var unsubscriptionsWaitingAck = ThreadSafeDictionary<UInt16, [String]>(label: "unsubscriptionsWaitingAck")
/// Sending messages
fileprivate var sendingMessages: [UInt16: CocoaMQTTMessage] = [:]
/// message id counter
private var _msgid: UInt16 = 0
fileprivate var socket: CocoaMQTTSocketProtocol
fileprivate var reader: CocoaMQTTReader?
// Closures
public var didConnectAck: (CocoaMQTT, CocoaMQTTConnAck) -> Void = { _, _ in }
public var didPublishMessage: (CocoaMQTT, CocoaMQTTMessage, UInt16) -> Void = { _, _, _ in }
public var didPublishAck: (CocoaMQTT, UInt16) -> Void = { _, _ in }
public var didReceiveMessage: (CocoaMQTT, CocoaMQTTMessage, UInt16) -> Void = { _, _, _ in }
public var didSubscribeTopics: (CocoaMQTT, NSDictionary, [String]) -> Void = { _, _, _ in }
public var didUnsubscribeTopics: (CocoaMQTT, [String]) -> Void = { _, _ in }
public var didPing: (CocoaMQTT) -> Void = { _ in }
public var didReceivePong: (CocoaMQTT) -> Void = { _ in }
public var didDisconnect: (CocoaMQTT, Error?) -> Void = { _, _ in }
public var didReceiveTrust: (CocoaMQTT, SecTrust, @escaping (Bool) -> Swift.Void) -> Void = { _, _, _ in }
public var didCompletePublish: (CocoaMQTT, UInt16) -> Void = { _, _ in }
public var didChangeState: (CocoaMQTT, CocoaMQTTConnState) -> Void = { _, _ in }
public var didScheduleReconnect: (CocoaMQTT, UInt, UInt16) -> Void = { _, _, _ in }
/// Initial client object
///
/// - Parameters:
/// - clientID: Client Identifier
/// - host: The MQTT broker host domain or IP address. Default is "localhost"
/// - port: The MQTT service port of host. Default is 1883
public init(clientID: String, host: String = "localhost", port: UInt16 = 1883, socket: CocoaMQTTSocketProtocol = CocoaMQTTSocket()) {
self.clientID = clientID
self.host = host
self.port = port
self.socket = socket
super.init()
deliver.delegate = self
if let storage = CocoaMQTTStorage() {
storage.setMQTTVersion("3.1.1")
} else {
printWarning("Localstorage initial failed for key: \(clientID)")
}
}
deinit {
aliveTimer?.suspend()
autoReconnTimer?.suspend()
socket.setDelegate(nil, delegateQueue: nil)
socket.disconnect()
}
fileprivate func send(_ frame: Frame, tag: Int = 0) {
printDebug("SEND: \(frame)")
let data = frame.bytes(version: version)
socket.write(Data(bytes: data, count: data.count), withTimeout: 5, tag: tag)
}
fileprivate func sendConnectFrame() {
var connect = FrameConnect(clientID: clientID)
connect.keepAlive = keepAlive
connect.username = username
connect.password = password
connect.willMsg = willMessage
connect.cleansess = cleanSession
send(connect)
reader!.start()
}
fileprivate func nextMessageID() -> UInt16 {
if _msgid == UInt16.max {
_msgid = 0
}
_msgid += 1
return _msgid
}
fileprivate func puback(_ type: FrameType, msgid: UInt16) {
switch type {
case .puback:
send(FramePubAck(msgid: msgid))
case .pubrec:
send(FramePubRec(msgid: msgid))
case .pubcomp:
send(FramePubComp(msgid: msgid))
default: return
}
}
/// Connect to MQTT broker
///
/// - Returns:
/// - Bool: It indicates whether successfully calling socket connect function.
/// Not yet established correct MQTT session
public func connect() -> Bool {
return connect(timeout: -1)
}
/// Connect to MQTT broker
/// - Parameters:
/// - timeout: Connect timeout
/// - Returns:
/// - Bool: It indicates whether successfully calling socket connect function.
/// Not yet established correct MQTT session
public func connect(timeout: TimeInterval) -> Bool {
socket.setDelegate(self, delegateQueue: delegateQueue)
reader = CocoaMQTTReader(socket: socket, delegate: self)
do {
if timeout > 0 {
try socket.connect(toHost: self.host, onPort: self.port, withTimeout: timeout)
} else {
try socket.connect(toHost: self.host, onPort: self.port)
}
delegateQueue.async { [weak self] in
guard let self = self else { return }
self.connState = .connecting
}
return true
} catch let error as NSError {
printError("socket connect error: \(error.description)")
return false
}
}
/// Send a DISCONNECT packet to the broker then close the connection
///
/// - Note: Only can be called from outside.
/// This closes the connection expectedly, so auto-reconnect will not run.
public func disconnect() {
expected_disconnect()
}
/// Disconnect unexpectedly.
/// This keeps auto-reconnect behavior enabled.
func internal_disconnect() {
is_internal_disconnected = false
socket.disconnect()
}
private func expected_disconnect() {
is_internal_disconnected = true
send(FrameDisconnect(), tag: -0xE0)
socket.disconnect()
}
/// Send a PING request to broker
public func ping() {
printDebug("ping")
send(FramePingReq(), tag: -0xC0)
__delegate_queue {
self.delegate?.mqttDidPing(self)
self.didPing(self)
}
}
/// Publish a message to broker
///
/// - Parameters:
/// - topic: Topic Name. It can not contain '#', '+' wildcards
/// - string: Payload string
/// - qos: Qos. Default is Qos1
/// - retained: Retained flag. Mark this message is a retained message. default is false
/// - Returns:
/// - 0 will be returned, if the message's qos is qos0
/// - 1-65535 will be returned, if the messages's qos is qos1/qos2
/// - -1 will be returned, if the messages queue is full
@discardableResult
public func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS = .qos1, retained: Bool = false) -> Int {
let message = CocoaMQTTMessage(topic: topic, string: string, qos: qos, retained: retained)
return publish(message)
}
/// Publish a message to broker
///
/// - Parameters:
/// - message: Message
@discardableResult
public func publish(_ message: CocoaMQTTMessage) -> Int {
let msgid: UInt16
if message.qos == .qos0 {
msgid = 0
} else {
msgid = nextMessageID()
}
var frame = FramePublish(topic: message.topic,
payload: message.payload,
qos: message.qos,
msgid: msgid)
frame.retained = message.retained
delegateQueue.async {
self.sendingMessages[msgid] = message
}
// Push frame to deliver message queue
guard deliver.add(frame) else {
delegateQueue.async {
self.sendingMessages.removeValue(forKey: msgid)
}
return -1
}
return Int(msgid)
}
/// Subscribe a `<Topic Name>/<Topic Filter>`
///
/// - Parameters:
/// - topic: Topic Name or Topic Filter
/// - qos: Qos. Default is qos1
public func subscribe(_ topic: String, qos: CocoaMQTTQoS = .qos1) {
return subscribe([(topic, qos)])
}
/// Subscribe a lists of topics
///
/// - Parameters:
/// - topics: A list of tuples presented by `(<Topic Names>/<Topic Filters>, Qos)`
public func subscribe(_ topics: [(String, CocoaMQTTQoS)]) {
let msgid = nextMessageID()
let frame = FrameSubscribe(msgid: msgid, topics: topics)
send(frame, tag: Int(msgid))
subscriptionsWaitingAck[msgid] = topics
}
/// Unsubscribe a Topic
///
/// - Parameters:
/// - topic: A Topic Name or Topic Filter
public func unsubscribe(_ topic: String) {
return unsubscribe([topic])
}
/// Unsubscribe a list of topics
///
/// - Parameters:
/// - topics: A list of `<Topic Names>/<Topic Filters>`
public func unsubscribe(_ topics: [String]) {
let msgid = nextMessageID()
let frame = FrameUnsubscribe(msgid: msgid, topics: topics)
unsubscriptionsWaitingAck[msgid] = topics
send(frame, tag: Int(msgid))
}
}
// MARK: CocoaMQTTDeliverProtocol
extension CocoaMQTT: CocoaMQTTDeliverProtocol {
func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) {
if let publish = frame as? FramePublish {
let msgid = publish.msgid
var message: CocoaMQTTMessage?
if let sendingMessage = sendingMessages[msgid] {
message = sendingMessage
// printError("Want send \(frame), but not found in CocoaMQTT cache")
} else {
message = CocoaMQTTMessage(topic: publish.topic, payload: publish.payload())
}
send(publish, tag: Int(msgid))
if let message = message {
self.delegate?.mqtt(self, didPublishMessage: message, id: msgid)
self.didPublishMessage(self, message, msgid)
}
} else if let pubrel = frame as? FramePubRel {
// -- Send PUBREL
send(pubrel, tag: Int(pubrel.msgid))
}
}
}
extension CocoaMQTT {
func __delegate_queue(_ fun: @escaping () -> Void) {
delegateQueue.async { [weak self] in
guard self != nil else { return }
fun()
}
}
private func prepareAutoReconnectAttempt() {
if reconnectTimeInterval == 0 {
reconnectTimeInterval = min(autoReconnectTimeInterval, maxAutoReconnectTimeInterval)
}
reconnectAttemptCount += 1
}
private func updateAutoReconnectIntervalForNextAttempt() {
let doubledInterval = UInt32(reconnectTimeInterval) * 2
reconnectTimeInterval = UInt16(min(doubledInterval, UInt32(maxAutoReconnectTimeInterval)))
}
private func resetAutoReconnectState() {
reconnectTimeInterval = 0
reconnectAttemptCount = 0
autoReconnTimer = nil
}
private func notifyAutoReconnectScheduled() {
delegate?.mqtt?(self, didScheduleReconnect: reconnectAttemptCount, after: reconnectTimeInterval)
didScheduleReconnect(self, reconnectAttemptCount, reconnectTimeInterval)
}
}
// MARK: - CocoaMQTTSocketDelegate
extension CocoaMQTT: CocoaMQTTSocketDelegate {
public func socketConnected(_ socket: CocoaMQTTSocketProtocol) {
sendConnectFrame()
}
public func socket(_ socket: CocoaMQTTSocketProtocol,
didReceive trust: SecTrust,
completionHandler: @escaping (Bool) -> Swift.Void) {
printDebug("Call the SSL/TLS manually validating function")
delegate?.mqtt?(self, didReceive: trust, completionHandler: completionHandler)
didReceiveTrust(self, trust, completionHandler)
}
public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
printDebug("Call the SSL/TLS manually validating function - socketUrlSession")
delegate?.mqttUrlSession?(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler)
}
// ?
public func socketDidSecure(_ sock: MGCDAsyncSocket) {
printDebug("Socket has successfully completed SSL/TLS negotiation")
sendConnectFrame()
}
public func socket(_ socket: CocoaMQTTSocketProtocol, didWriteDataWithTag tag: Int) {
// XXX: How to print writed bytes??
}
public func socket(_ socket: CocoaMQTTSocketProtocol, didRead data: Data, withTag tag: Int) {
let etag = CocoaMQTTReadTag(rawValue: tag)!
var bytes = [UInt8]([0])
switch etag {
case CocoaMQTTReadTag.header:
data.copyBytes(to: &bytes, count: 1)
reader!.headerReady(bytes[0])
case CocoaMQTTReadTag.length:
data.copyBytes(to: &bytes, count: 1)
reader!.lengthReady(bytes[0])
case CocoaMQTTReadTag.payload:
reader!.payloadReady(data)
}
}
public func socketDidDisconnect(_ socket: CocoaMQTTSocketProtocol, withError err: Error?) {
// Clean up
socket.setDelegate(nil, delegateQueue: nil)
if is_internal_disconnected || !autoReconnect {
resetAutoReconnectState()
}
connState = .disconnected
delegate?.mqttDidDisconnect(self, withError: err)
didDisconnect(self, err)
guard !is_internal_disconnected else {
is_internal_disconnected = false
return
}
guard autoReconnect else {
resetAutoReconnectState()
return
}
prepareAutoReconnectAttempt()
// Start reconnector once socket error occurred
printInfo("Try reconnect to server after \(reconnectTimeInterval)s")
notifyAutoReconnectScheduled()
autoReconnTimer = CocoaMQTTTimer.after(Double(reconnectTimeInterval), name: "autoReconnTimer", { [weak self] in
guard let self = self else { return }
self.updateAutoReconnectIntervalForNextAttempt()
_ = self.connect()
})
}
}
// MARK: - CocoaMQTTReaderDelegate
extension CocoaMQTT: CocoaMQTTReaderDelegate {
func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck) {
printDebug("RECV: \(connack)")
if connack.returnCode == .accept {
// Disable auto-reconnect
resetAutoReconnectState()
is_internal_disconnected = false
// Start keepalive timer
let interval = Double(keepAlive <= 0 ? 60: keepAlive)
aliveTimer = CocoaMQTTTimer.every(interval, name: "aliveTimer") { [weak self] in
guard let self = self else { return }
self.delegateQueue.async {
guard self.connState == .connected else {
self.aliveTimer = nil
return
}
self.ping()
}
}
// recover session if enable
if cleanSession {
deliver.cleanAll()
} else {
if let storage = CocoaMQTTStorage(by: clientID) {
deliver.recoverSessionBy(storage)
} else {
printWarning("Localstorage initial failed for key: \(clientID)")
}
}
connState = .connected
} else {
connState = .disconnected
expected_disconnect()
}
delegate?.mqtt(self, didConnectAck: connack.returnCode ?? CocoaMQTTConnAck.serverUnavailable)
didConnectAck(self, connack.returnCode ?? CocoaMQTTConnAck.serverUnavailable)
}
func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish) {
printDebug("RECV: \(publish)")
let message = CocoaMQTTMessage(topic: publish.topic, payload: publish.payload(), qos: publish.qos, retained: publish.retained)
message.duplicated = publish.dup
printInfo("Received message: \(message)")
delegate?.mqtt(self, didReceiveMessage: message, id: publish.msgid)
didReceiveMessage(self, message, publish.msgid)
if message.qos == .qos1 {
puback(FrameType.puback, msgid: publish.msgid)
} else if message.qos == .qos2 {
puback(FrameType.pubrec, msgid: publish.msgid)
}
}
func didReceive(_ reader: CocoaMQTTReader, puback: FramePubAck) {
printDebug("RECV: \(puback)")
deliver.ack(by: puback)
delegate?.mqtt(self, didPublishAck: puback.msgid)
didPublishAck(self, puback.msgid)
}
func didReceive(_ reader: CocoaMQTTReader, pubrec: FramePubRec) {
printDebug("RECV: \(pubrec)")
deliver.ack(by: pubrec)
}
func didReceive(_ reader: CocoaMQTTReader, pubrel: FramePubRel) {
printDebug("RECV: \(pubrel)")
puback(FrameType.pubcomp, msgid: pubrel.msgid)
}
func didReceive(_ reader: CocoaMQTTReader, pubcomp: FramePubComp) {
printDebug("RECV: \(pubcomp)")
deliver.ack(by: pubcomp)
delegate?.mqtt?(self, didPublishComplete: pubcomp.msgid)
didCompletePublish(self, pubcomp.msgid)
}
func didReceive(_ reader: CocoaMQTTReader, suback: FrameSubAck) {
printDebug("RECV: \(suback)")
guard let topicsAndQos = subscriptionsWaitingAck.removeValue(forKey: suback.msgid) else {
printWarning("UNEXPECT SUBACK Received: \(suback)")
return
}
guard topicsAndQos.count == suback.grantedQos.count else {
printWarning("UNEXPECT SUBACK Recivied: \(suback)")
return
}
let success: NSMutableDictionary = NSMutableDictionary()
var failed = [String]()
for (idx, (topic, _)) in topicsAndQos.enumerated() {
if suback.grantedQos[idx] != .FAILURE {
subscriptionsStorage[topic] = suback.grantedQos[idx]
success[topic] = suback.grantedQos[idx].rawValue
} else {
failed.append(topic)
}
}
delegate?.mqtt(self, didSubscribeTopics: success, failed: failed)
didSubscribeTopics(self, success, failed)
}
func didReceive(_ reader: CocoaMQTTReader, unsuback: FrameUnsubAck) {
printDebug("RECV: \(unsuback)")
guard let topics = unsubscriptionsWaitingAck.removeValue(forKey: unsuback.msgid) else {
printWarning("UNEXPECT UNSUBACK Received: \(unsuback.msgid)")
return
}
// Remove local subscription
for t in topics {
subscriptionsStorage.removeValue(forKey: t)
}
delegate?.mqtt(self, didUnsubscribeTopics: topics)
didUnsubscribeTopics(self, topics)
}
func didReceive(_ reader: CocoaMQTTReader, pingresp: FramePingResp) {
printDebug("RECV: \(pingresp)")
delegate?.mqttDidReceivePong(self)
didReceivePong(self)
}
func didReceive(_ reader: CocoaMQTTReader, disconnect: FrameDisconnect) {
printWarning("Received DISCONNECT in MQTT 3.1.1 mode, closing socket")
internal_disconnect()
}
func didReceive(_ reader: CocoaMQTTReader, auth: FrameAuth) {
printWarning("Received AUTH in MQTT 3.1.1 mode, closing socket")
internal_disconnect()
}
}

903
Pods/CocoaMQTT/Source/CocoaMQTT5.swift generated Normal file
View File

@ -0,0 +1,903 @@
//
// CocoaMQTT5.swift
// CocoaMQTT5
//
// Created by Feng Lee<feng@eqmtt.io> on 14/8/3.
// Copyright (c) 2015 emqx.io. All rights reserved.
//
import Foundation
import MqttCocoaAsyncSocket
/**
* Connection State
*/
@objc public enum CocoaMQTTConnState: UInt8, CustomStringConvertible {
case disconnected = 0
case connecting
case connected
public var description: String {
switch self {
case .connecting: return "connecting"
case .connected: return "connected"
case .disconnected: return "disconnected"
}
}
}
/// CocoaMQTT5 Delegate
@objc public protocol CocoaMQTT5Delegate {
///
func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishMessage message: CocoaMQTT5Message, id: UInt16)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishAck id: UInt16, pubAckData: MqttDecodePubAck?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishRec id: UInt16, pubRecData: MqttDecodePubRec?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveMessage message: CocoaMQTT5Message, id: UInt16, publishData: MqttDecodePublish?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didSubscribeTopics success: NSDictionary, failed: [String], subAckData: MqttDecodeSubAck?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], unsubAckData: MqttDecodeUnsubAck?)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveDisconnectReasonCode reasonCode: CocoaMQTTDISCONNECTReasonCode)
///
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveAuthReasonCode reasonCode: CocoaMQTTAUTHReasonCode)
///
func mqtt5DidPing(_ mqtt5: CocoaMQTT5)
///
func mqtt5DidReceivePong(_ mqtt5: CocoaMQTT5)
///
func mqtt5DidDisconnect(_ mqtt5: CocoaMQTT5, withError err: Error?)
/// Manually validate SSL/TLS server certificate.
///
/// This method will be called if enable `allowUntrustCACertificate`
@objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void)
@objc optional func mqtt5UrlSession(_ mqtt: CocoaMQTT5, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
///
@objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didPublishComplete id: UInt16, pubCompData: MqttDecodePubComp?)
///
@objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didStateChangeTo state: CocoaMQTTConnState)
/// Called when auto-reconnect schedules a reconnect attempt after an unexpected disconnect.
@objc optional func mqtt5(_ mqtt5: CocoaMQTT5, didScheduleReconnect attemptCount: UInt, after interval: UInt16)
}
/// set mqtt version to 5.0
public func setMqtt5Version() {
if let storage = CocoaMQTTStorage() {
storage.setMQTTVersion("5.0")
}
}
/**
* Blueprint of the MQTT Client
*/
protocol CocoaMQTT5Client {
/* Basic Properties */
var host: String { get set }
var port: UInt16 { get set }
var clientID: String { get }
var username: String? {get set}
var password: String? {get set}
var cleanSession: Bool {get set}
var keepAlive: UInt16 {get set}
var willMessage: CocoaMQTT5Message? {get set}
var connectProperties: MqttConnectProperties? {get set}
var authProperties: MqttAuthProperties? {get set}
/* Basic Properties */
/* CONNNEC/DISCONNECT */
func connect() -> Bool
func connect(timeout: TimeInterval) -> Bool
func disconnect()
func ping()
/* CONNNEC/DISCONNECT */
/* PUBLISH/SUBSCRIBE */
func subscribe(_ topic: String, qos: CocoaMQTTQoS)
func subscribe(_ topics: [MqttSubscription])
func unsubscribe(_ topic: String)
func unsubscribe(_ topics: [MqttSubscription])
func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS, DUP: Bool, retained: Bool, properties: MqttPublishProperties) -> Int
func publish(_ message: CocoaMQTT5Message, DUP: Bool, retained: Bool, properties: MqttPublishProperties) -> Int
/* PUBLISH/SUBSCRIBE */
}
/// MQTT Client
///
/// - Note: MGCDAsyncSocket need delegate to extend NSObject
public class CocoaMQTT5: NSObject, CocoaMQTT5Client {
public weak var delegate: CocoaMQTT5Delegate?
private var version = "5.0"
public var host = "localhost"
public var port: UInt16 = 1883
public var clientID: String
public var username: String?
public var password: String?
/// Clean Session flag. Default is true
///
/// - TODO: What's behavior each Clean Session flags???
public var cleanSession = true
/// Setup a **Last Will Message** to client before connecting to broker
public var willMessage: CocoaMQTT5Message?
/// Enable backgounding socket if running on iOS platform. Default is true
///
/// - Note:
public var backgroundOnSocket: Bool {
get { return (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket ?? true }
set { (self.socket as? CocoaMQTTSocket)?.backgroundOnSocket = newValue }
}
/// Delegate Executed queue. Default is `DispatchQueue.main`
///
/// The delegate/closure callback function will be committed asynchronously to it
public var delegateQueue = DispatchQueue.main
@ConcurrentAtomic(wrappedValue: CocoaMQTTConnState.disconnected, label: "CocoaMQTT5.connState")
public var connState {
didSet {
__delegate_queue {
self.delegate?.mqtt5?(self, didStateChangeTo: self.connState)
self.didChangeState(self, self.connState)
}
}
}
// deliver
private var deliver = CocoaMQTTDeliver()
/// Re-deliver the un-acked messages
public var deliverTimeout: Double {
get { return deliver.retryTimeInterval }
set { deliver.retryTimeInterval = newValue }
}
/// Message queue size. default 1000
///
/// The new publishing messages of Qos1/Qos2 will be drop, if the queue is full
public var messageQueueSize: UInt {
get { return deliver.mqueueSize }
set { deliver.mqueueSize = newValue }
}
/// In-flight window size. default 10
public var inflightWindowSize: UInt {
get { return deliver.inflightWindowSize }
set { deliver.inflightWindowSize = newValue }
}
/// Keep alive time interval
public var keepAlive: UInt16 = 60
private var aliveTimer: CocoaMQTTTimer?
/// Enable auto-reconnect mechanism
public var autoReconnect = false
/// Reconnect time interval
///
/// - note: This value will be increased with `autoReconnectTimeInterval *= 2`
/// if reconnect failed
public var autoReconnectTimeInterval: UInt16 = 1 // starts from 1 second
/// Maximum auto reconnect time interval
///
/// The timer starts from `autoReconnectTimeInterval` second and grows exponentially until this value
/// After that, it uses this value for subsequent requests.
public var maxAutoReconnectTimeInterval: UInt16 = 128 // 128 seconds
/// 3.1.2.11 CONNECT Properties
public var connectProperties: MqttConnectProperties?
/// 3.15.2.2 AUTH Properties
public var authProperties: MqttAuthProperties?
/// Auto-reconnect backoff interval in seconds for the current reconnect cycle.
///
/// This value is advanced for the next reconnect attempt while auto-reconnect is active,
/// and resets to `0` when auto-reconnect is inactive.
public private(set) var reconnectTimeInterval: UInt16 = 0
/// Number of reconnect attempts scheduled in the current auto-reconnect cycle.
///
/// The value resets to `0` after a successful connection or expected disconnect.
public private(set) var reconnectAttemptCount: UInt = 0
private var autoReconnTimer: CocoaMQTTTimer?
private var is_internal_disconnected = false
/// Console log level
public var logLevel: CocoaMQTTLoggerLevel {
get {
return CocoaMQTTLogger.logger.minLevel
}
set {
CocoaMQTTLogger.logger.minLevel = newValue
}
}
/// Enable SSL connection
public var enableSSL: Bool {
get { return self.socket.enableSSL }
set { socket.enableSSL = newValue }
}
///
public var sslSettings: [String: NSObject]? {
get { return (self.socket as? CocoaMQTTSocket)?.sslSettings ?? nil }
set { (self.socket as? CocoaMQTTSocket)?.sslSettings = newValue }
}
/// Allow self-signed ca certificate.
///
/// Default is false
public var allowUntrustCACertificate: Bool {
get { return (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate ?? false }
set { (self.socket as? CocoaMQTTSocket)?.allowUntrustCACertificate = newValue }
}
/// The subscribed topics in current communication
public var subscriptions = ThreadSafeDictionary<String, CocoaMQTTQoS>(label: "subscriptions")
fileprivate var subscriptionsWaitingAck = ThreadSafeDictionary<UInt16, [MqttSubscription]>(label: "subscriptionsWaitingAck")
fileprivate var unsubscriptionsWaitingAck = ThreadSafeDictionary<UInt16, [MqttSubscription]>(label: "unsubscriptionsWaitingAck")
/// Sending messages
fileprivate var sendingMessages: [UInt16: CocoaMQTT5Message] = [:]
/// message id counter
private var _msgid: UInt16 = 0
fileprivate var socket: CocoaMQTTSocketProtocol
fileprivate var reader: CocoaMQTTReader?
// Closures
public var didConnectAck: (CocoaMQTT5, CocoaMQTTCONNACKReasonCode, MqttDecodeConnAck?) -> Void = { _, _, _ in }
public var didPublishMessage: (CocoaMQTT5, CocoaMQTT5Message, UInt16) -> Void = { _, _, _ in }
public var didPublishAck: (CocoaMQTT5, UInt16, MqttDecodePubAck?) -> Void = { _, _, _ in }
public var didPublishRec: (CocoaMQTT5, UInt16, MqttDecodePubRec?) -> Void = { _, _, _ in }
public var didReceiveMessage: (CocoaMQTT5, CocoaMQTT5Message, UInt16, MqttDecodePublish?) -> Void = { _, _, _, _ in }
public var didSubscribeTopics: (CocoaMQTT5, NSDictionary, [String], MqttDecodeSubAck?) -> Void = { _, _, _, _ in }
public var didUnsubscribeTopics: (CocoaMQTT5, [String], MqttDecodeUnsubAck?) -> Void = { _, _, _ in }
public var didPing: (CocoaMQTT5) -> Void = { _ in }
public var didReceivePong: (CocoaMQTT5) -> Void = { _ in }
public var didDisconnect: (CocoaMQTT5, Error?) -> Void = { _, _ in }
public var didDisconnectReasonCode: (CocoaMQTT5, CocoaMQTTDISCONNECTReasonCode) -> Void = { _, _ in }
public var didAuthReasonCode: (CocoaMQTT5, CocoaMQTTAUTHReasonCode) -> Void = { _, _ in }
public var didReceiveTrust: (CocoaMQTT5, SecTrust, @escaping (Bool) -> Swift.Void) -> Void = { _, _, _ in }
public var didCompletePublish: (CocoaMQTT5, UInt16, MqttDecodePubComp?) -> Void = { _, _, _ in }
public var didChangeState: (CocoaMQTT5, CocoaMQTTConnState) -> Void = { _, _ in }
public var didScheduleReconnect: (CocoaMQTT5, UInt, UInt16) -> Void = { _, _, _ in }
/// Initial client object
///
/// - Parameters:
/// - clientID: Client Identifier
/// - host: The MQTT broker host domain or IP address. Default is "localhost"
/// - port: The MQTT service port of host. Default is 1883
public init(clientID: String, host: String = "localhost", port: UInt16 = 1883, socket: CocoaMQTTSocketProtocol = CocoaMQTTSocket()) {
self.clientID = clientID
self.host = host
self.port = port
self.socket = socket
super.init()
deliver.delegate = self
if let storage = CocoaMQTTStorage() {
storage.setMQTTVersion("5.0")
} else {
printWarning("Localstorage initial failed for key: \(clientID)")
}
}
deinit {
aliveTimer?.suspend()
autoReconnTimer?.suspend()
socket.setDelegate(nil, delegateQueue: nil)
socket.disconnect()
}
fileprivate func send(_ frame: Frame, tag: Int = 0) {
printDebug("SEND: \(frame)")
let data = frame.bytes(version: version)
socket.write(Data(bytes: data, count: data.count), withTimeout: 5, tag: tag)
}
fileprivate func sendConnectFrame() {
var connect = FrameConnect(clientID: clientID)
connect.keepAlive = keepAlive
connect.username = username
connect.password = password
connect.willMsg5 = willMessage
connect.cleansess = cleanSession
connect.connectProperties = connectProperties
send(connect)
reader!.start()
}
fileprivate func nextMessageID() -> UInt16 {
if _msgid == UInt16.max {
_msgid = 0
}
_msgid += 1
return _msgid
}
fileprivate func puback(_ type: FrameType, msgid: UInt16) {
switch type {
case .puback:
send(FramePubAck(msgid: msgid, reasonCode: CocoaMQTTPUBACKReasonCode.success))
case .pubrec:
send(FramePubRec(msgid: msgid, reasonCode: CocoaMQTTPUBRECReasonCode.success))
case .pubcomp:
send(FramePubComp(msgid: msgid, reasonCode: CocoaMQTTPUBCOMPReasonCode.success))
default: return
}
}
/// Connect to MQTT broker
///
/// - Returns:
/// - Bool: It indicates whether successfully calling socket connect function.
/// Not yet established correct MQTT session
public func connect() -> Bool {
return connect(timeout: -1)
}
/// Connect to MQTT broker
/// - Parameters:
/// - timeout: Connect timeout
/// - Returns:
/// - Bool: It indicates whether successfully calling socket connect function.
/// Not yet established correct MQTT session
public func connect(timeout: TimeInterval) -> Bool {
socket.setDelegate(self, delegateQueue: delegateQueue)
reader = CocoaMQTTReader(socket: socket, delegate: self)
do {
if timeout > 0 {
try socket.connect(toHost: self.host, onPort: self.port, withTimeout: timeout)
} else {
try socket.connect(toHost: self.host, onPort: self.port)
}
delegateQueue.async { [weak self] in
guard let self = self else { return }
self.connState = .connecting
}
return true
} catch let error as NSError {
printError("socket connect error: \(error.description)")
return false
}
}
/// Send a DISCONNECT packet to the broker then close the connection
///
/// - Note: Only can be called from outside.
/// This closes the connection expectedly, so auto-reconnect will not run.
public func disconnect() {
expected_disconnect(reasonCode: .normalDisconnection)
}
public func disconnect(reasonCode: CocoaMQTTDISCONNECTReasonCode, userProperties: [String: String] ) {
expected_disconnect(reasonCode: reasonCode, userProperties: userProperties)
}
/// Disconnect unexpectedly.
/// This keeps auto-reconnect behavior enabled.
func internal_disconnect() {
is_internal_disconnected = false
socket.disconnect()
}
func internal_disconnect_withProperties(reasonCode: CocoaMQTTDISCONNECTReasonCode, userProperties: [String: String] ) {
expected_disconnect(reasonCode: reasonCode, userProperties: userProperties)
}
private func expected_disconnect(reasonCode: CocoaMQTTDISCONNECTReasonCode, userProperties: [String: String]? = nil) {
is_internal_disconnected = true
var frameDisconnect = FrameDisconnect(disconnectReasonCode: reasonCode)
frameDisconnect.userProperties = userProperties ?? [:]
send(frameDisconnect, tag: -0xE0)
socket.disconnect()
}
/// Send a PING request to broker
public func ping() {
printDebug("ping")
send(FramePingReq(), tag: -0xC0)
__delegate_queue {
self.delegate?.mqtt5DidPing(self)
self.didPing(self)
}
}
/// Publish a message to broker
///
/// - Parameters:
/// - topic: Topic Name. It can not contain '#', '+' wildcards
/// - string: Payload string
/// - qos: Qos. Default is Qos1
/// - retained: Retained flag. Mark this message is a retained message. default is false
/// - properties: Publish Properties
/// - Returns:
/// - 0 will be returned, if the message's qos is qos0
/// - 1-65535 will be returned, if the messages's qos is qos1/qos2
/// - -1 will be returned, if the messages queue is full
@discardableResult
public func publish(_ topic: String, withString string: String, qos: CocoaMQTTQoS = .qos1, DUP: Bool = false, retained: Bool = false, properties: MqttPublishProperties) -> Int {
assert(!(DUP && qos == .qos0), "DUP=true with QoS0 is invalid for MQTT PUBLISH.")
guard !(DUP && qos == .qos0) else {
printError("Invalid PUBLISH flags: DUP=true requires QoS1 or QoS2.")
return -1
}
let message = CocoaMQTT5Message(topic: topic, string: string, qos: qos, retained: retained)
return publish(message, DUP: DUP, retained: retained, properties: properties)
}
/// Publish a message to broker
///
/// - Parameters:
/// - message: Message
/// - properties: Publish Properties
@discardableResult
public func publish(_ message: CocoaMQTT5Message, DUP: Bool = false, retained: Bool = false, properties: MqttPublishProperties) -> Int {
assert(!(DUP && message.qos == .qos0), "DUP=true with QoS0 is invalid for MQTT PUBLISH.")
guard !(DUP && message.qos == .qos0) else {
printError("Invalid PUBLISH flags: DUP=true requires QoS1 or QoS2.")
return -1
}
let msgid: UInt16
if message.qos == .qos0 {
msgid = 0
} else {
msgid = nextMessageID()
}
printDebug("message.topic \(message.topic ) = message.payload \(message.payload)")
var frame = FramePublish(topic: message.topic,
payload: message.payload,
qos: message.qos,
msgid: msgid)
frame.qos = message.qos
frame.dup = DUP
frame.publishProperties = properties
frame.retained = message.retained
delegateQueue.async {
self.sendingMessages[msgid] = message
}
// Push frame to deliver message queue
guard deliver.add(frame) else {
delegateQueue.async {
self.sendingMessages.removeValue(forKey: msgid)
}
return -1
}
return Int(msgid)
}
/// Subscribe a `<Topic Name>/<Topic Filter>`
///
/// - Parameters:
/// - topic: Topic Name or Topic Filter
/// - qos: Qos. Default is qos1
public func subscribe(_ topic: String, qos: CocoaMQTTQoS = .qos1) {
let filter = MqttSubscription(topic: topic, qos: qos)
return subscribe([filter])
}
/// Subscribe a lists of topics
///
/// - Parameters:
/// - topics: A list of tuples presented by `(<Topic Names>/<Topic Filters>, Qos)`
public func subscribe(_ topics: [MqttSubscription]) {
let msgid = nextMessageID()
let frame = FrameSubscribe(msgid: msgid, subscriptionList: topics)
send(frame, tag: Int(msgid))
subscriptionsWaitingAck[msgid] = topics
}
/// Subscribe a lists of topics
///
/// - Parameters:
/// - topics: A list of tuples presented by `(<Topic Names>/<Topic Filters>, Qos)`
/// - packetIdentifier: SUBSCRIBE Variable Header
/// - subscriptionIdentifier: Subscription Identifier
/// - userProperty: User Property
public func subscribe(_ topics: [MqttSubscription], packetIdentifier: UInt16? = nil, subscriptionIdentifier: UInt32? = nil, userProperty: [String: String] = [:]) {
let msgid = nextMessageID()
let frame = FrameSubscribe(msgid: msgid, subscriptionList: topics, packetIdentifier: packetIdentifier, subscriptionIdentifier: subscriptionIdentifier, userProperty: userProperty)
send(frame, tag: Int(msgid))
subscriptionsWaitingAck[msgid] = topics
}
/// Unsubscribe a Topic
///
/// - Parameters:
/// - topic: A Topic Name or Topic Filter
public func unsubscribe(_ topic: String) {
let filter = MqttSubscription(topic: topic)
return unsubscribe([filter])
}
/// Unsubscribe a list of topics
///
/// - Parameters:
/// - topics: A list of `<Topic Names>/<Topic Filters>`
public func unsubscribe(_ topics: [MqttSubscription]) {
let msgid = nextMessageID()
let frame = FrameUnsubscribe(msgid: msgid, topics: topics)
unsubscriptionsWaitingAck[msgid] = topics
send(frame, tag: Int(msgid))
}
/// Authentication exchange
///
///
public func auth(reasonCode: CocoaMQTTAUTHReasonCode, authProperties: MqttAuthProperties) {
printDebug("auth")
let frame = FrameAuth(reasonCode: reasonCode, authProperties: authProperties)
send(frame)
}
}
// MARK: CocoaMQTTDeliverProtocol
extension CocoaMQTT5: CocoaMQTTDeliverProtocol {
func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame) {
if let publish = frame as? FramePublish {
let msgid = publish.msgid
var message: CocoaMQTT5Message?
if let sendingMessage = sendingMessages[msgid] {
message = sendingMessage
// printError("Want send \(frame), but not found in CocoaMQTT cache")
} else {
message = CocoaMQTT5Message(topic: publish.topic, payload: publish.payload())
}
send(publish, tag: Int(msgid))
if let message = message {
self.delegate?.mqtt5(self, didPublishMessage: message, id: msgid)
self.didPublishMessage(self, message, msgid)
}
} else if let pubrel = frame as? FramePubRel {
// -- Send PUBREL
send(pubrel, tag: Int(pubrel.msgid))
}
}
}
extension CocoaMQTT5 {
func __delegate_queue(_ fun: @escaping () -> Void) {
delegateQueue.async { [weak self] in
guard self != nil else { return }
fun()
}
}
private func prepareAutoReconnectAttempt() {
if reconnectTimeInterval == 0 {
reconnectTimeInterval = min(autoReconnectTimeInterval, maxAutoReconnectTimeInterval)
}
reconnectAttemptCount += 1
}
private func updateAutoReconnectIntervalForNextAttempt() {
let doubledInterval = UInt32(reconnectTimeInterval) * 2
reconnectTimeInterval = UInt16(min(doubledInterval, UInt32(maxAutoReconnectTimeInterval)))
}
private func resetAutoReconnectState() {
reconnectTimeInterval = 0
reconnectAttemptCount = 0
autoReconnTimer = nil
}
private func notifyAutoReconnectScheduled() {
delegate?.mqtt5?(self, didScheduleReconnect: reconnectAttemptCount, after: reconnectTimeInterval)
didScheduleReconnect(self, reconnectAttemptCount, reconnectTimeInterval)
}
}
// MARK: - CocoaMQTTSocketDelegate
extension CocoaMQTT5: CocoaMQTTSocketDelegate {
public func socketConnected(_ socket: CocoaMQTTSocketProtocol) {
sendConnectFrame()
}
public func socket(_ socket: CocoaMQTTSocketProtocol,
didReceive trust: SecTrust,
completionHandler: @escaping (Bool) -> Swift.Void) {
printDebug("Call the SSL/TLS manually validating function")
delegate?.mqtt5?(self, didReceive: trust, completionHandler: completionHandler)
didReceiveTrust(self, trust, completionHandler)
}
public func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
printDebug("Call the SSL/TLS manually validating function - socketUrlSession")
delegate?.mqtt5UrlSession?(self, didReceiveTrust: trust, didReceiveChallenge: challenge, completionHandler: completionHandler)
}
// ?
public func socketDidSecure(_ sock: MGCDAsyncSocket) {
printDebug("Socket has successfully completed SSL/TLS negotiation")
sendConnectFrame()
}
public func socket(_ socket: CocoaMQTTSocketProtocol, didWriteDataWithTag tag: Int) {
// XXX: How to print writed bytes??
}
public func socket(_ socket: CocoaMQTTSocketProtocol, didRead data: Data, withTag tag: Int) {
let etag = CocoaMQTTReadTag(rawValue: tag)!
var bytes = [UInt8]([0])
switch etag {
case CocoaMQTTReadTag.header:
data.copyBytes(to: &bytes, count: 1)
reader!.headerReady(bytes[0])
case CocoaMQTTReadTag.length:
data.copyBytes(to: &bytes, count: 1)
reader!.lengthReady(bytes[0])
case CocoaMQTTReadTag.payload:
reader!.payloadReady(data)
}
}
public func socketDidDisconnect(_ socket: CocoaMQTTSocketProtocol, withError err: Error?) {
// Clean up
socket.setDelegate(nil, delegateQueue: nil)
if is_internal_disconnected || !autoReconnect {
resetAutoReconnectState()
}
connState = .disconnected
delegate?.mqtt5DidDisconnect(self, withError: err)
didDisconnect(self, err)
guard !is_internal_disconnected else {
is_internal_disconnected = false
return
}
guard autoReconnect else {
resetAutoReconnectState()
return
}
prepareAutoReconnectAttempt()
// Start reconnector once socket error occurred
printInfo("Try reconnect to server after \(reconnectTimeInterval)s")
notifyAutoReconnectScheduled()
autoReconnTimer = CocoaMQTTTimer.after(Double(reconnectTimeInterval), name: "autoReconnTimer", { [weak self] in
guard let self = self else { return }
self.updateAutoReconnectIntervalForNextAttempt()
_ = self.connect()
})
}
}
// MARK: - CocoaMQTTReaderDelegate
extension CocoaMQTT5: CocoaMQTTReaderDelegate {
func didReceive(_ reader: CocoaMQTTReader, disconnect: FrameDisconnect) {
let reasonCode = disconnect.receiveReasonCode ?? .normalDisconnection
delegate?.mqtt5(self, didReceiveDisconnectReasonCode: reasonCode)
didDisconnectReasonCode(self, reasonCode)
}
func didReceive(_ reader: CocoaMQTTReader, auth: FrameAuth) {
let reasonCode = auth.receiveReasonCode ?? .success
delegate?.mqtt5(self, didReceiveAuthReasonCode: reasonCode)
didAuthReasonCode(self, reasonCode)
}
func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck) {
printDebug("RECV: \(connack)")
if connack.reasonCode == .success {
// Disable auto-reconnect
resetAutoReconnectState()
is_internal_disconnected = false
// Start keepalive timer
let interval = Double(keepAlive <= 0 ? 60: keepAlive)
aliveTimer = CocoaMQTTTimer.every(interval, name: "aliveTimer") { [weak self] in
guard let self = self else { return }
self.delegateQueue.async {
guard self.connState == .connected else {
self.aliveTimer = nil
return
}
self.ping()
}
}
// recover session if enable
if cleanSession {
deliver.cleanAll()
} else {
if let storage = CocoaMQTTStorage(by: clientID) {
deliver.recoverSessionBy(storage)
} else {
printWarning("Localstorage initial failed for key: \(clientID)")
}
}
connState = .connected
} else {
connState = .disconnected
expected_disconnect(reasonCode: .normalDisconnection)
}
delegate?.mqtt5(self, didConnectAck: connack.reasonCode ?? CocoaMQTTCONNACKReasonCode.unspecifiedError, connAckData: connack.connackProperties ?? nil)
didConnectAck(self, connack.reasonCode ?? CocoaMQTTCONNACKReasonCode.unspecifiedError, connack.connackProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish) {
printDebug("RECV: \(publish)")
let message = CocoaMQTT5Message(topic: publish.mqtt5Topic, payload: publish.payload5(), qos: publish.qos, retained: publish.retained)
message.duplicated = publish.dup
message.contentType = publish.publishRecProperties?.contentType
printInfo("Received message: \(message)")
delegate?.mqtt5(self, didReceiveMessage: message, id: publish.msgid, publishData: publish.publishRecProperties ?? nil)
didReceiveMessage(self, message, publish.msgid, publish.publishRecProperties ?? nil)
if message.qos == .qos1 {
puback(FrameType.puback, msgid: publish.msgid)
} else if message.qos == .qos2 {
puback(FrameType.pubrec, msgid: publish.msgid)
}
}
func didReceive(_ reader: CocoaMQTTReader, puback: FramePubAck) {
printDebug("RECV: \(puback)")
deliver.ack(by: puback)
delegate?.mqtt5(self, didPublishAck: puback.msgid, pubAckData: puback.pubAckProperties ?? nil)
didPublishAck(self, puback.msgid, puback.pubAckProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, pubrec: FramePubRec) {
printDebug("RECV: \(pubrec)")
deliver.ack(by: pubrec)
delegate?.mqtt5(self, didPublishRec: pubrec.msgid, pubRecData: pubrec.pubRecProperties ?? nil)
didPublishRec(self, pubrec.msgid, pubrec.pubRecProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, pubrel: FramePubRel) {
printDebug("RECV: \(pubrel)")
puback(FrameType.pubcomp, msgid: pubrel.msgid)
}
func didReceive(_ reader: CocoaMQTTReader, pubcomp: FramePubComp) {
printDebug("RECV: \(pubcomp)")
deliver.ack(by: pubcomp)
delegate?.mqtt5?(self, didPublishComplete: pubcomp.msgid, pubCompData: pubcomp.pubCompProperties ?? nil)
didCompletePublish(self, pubcomp.msgid, pubcomp.pubCompProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, suback: FrameSubAck) {
printDebug("RECV: \(suback)")
guard let topicsAndQos = subscriptionsWaitingAck.removeValue(forKey: suback.msgid) else {
printWarning("UNEXPECT SUBACK Received: \(suback)")
return
}
guard topicsAndQos.count == suback.grantedQos.count else {
printWarning("UNEXPECT SUBACK Recivied: \(suback)")
return
}
let success: NSMutableDictionary = NSMutableDictionary()
var failed = [String]()
for (idx, subscriptionList) in topicsAndQos.enumerated() {
if suback.grantedQos[idx] != .FAILURE {
subscriptions[subscriptionList.topic] = suback.grantedQos[idx]
success[subscriptionList.topic] = suback.grantedQos[idx].rawValue
} else {
failed.append(subscriptionList.topic)
}
}
delegate?.mqtt5(self, didSubscribeTopics: success, failed: failed, subAckData: suback.subAckProperties ?? nil)
didSubscribeTopics(self, success, failed, suback.subAckProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, unsuback: FrameUnsubAck) {
printDebug("RECV: \(unsuback)")
guard let topics = unsubscriptionsWaitingAck.removeValue(forKey: unsuback.msgid) else {
printWarning("UNEXPECT UNSUBACK Received: \(unsuback.msgid)")
return
}
// Remove local subscription
var removeTopics: [String] = []
for t in topics {
removeTopics.append(t.topic)
subscriptions.removeValue(forKey: t.topic)
}
delegate?.mqtt5(self, didUnsubscribeTopics: removeTopics, unsubAckData: unsuback.unSubAckProperties ?? nil)
didUnsubscribeTopics(self, removeTopics, unsuback.unSubAckProperties ?? nil)
}
func didReceive(_ reader: CocoaMQTTReader, pingresp: FramePingResp) {
printDebug("RECV: \(pingresp)")
delegate?.mqtt5DidReceivePong(self)
didReceivePong(self)
}
}

View File

@ -0,0 +1,155 @@
//
// CocoaMQTT5Message.swift
// CocoaMQTT
//
// Created by Created by liwei wang on 2021/11/10.
// Copyright (c) 2015 emqx.io. All rights reserved.
//
import Foundation
/// MQTT Message
public class CocoaMQTT5Message: NSObject {
public var qos = CocoaMQTTQoS.qos1
public var topic: String
public var payload: [UInt8]
public var retained = false
/// The `duplicated` property show that this message maybe has be received before
///
/// - note: Readonly property
public var duplicated = false
/// 3.1.3.2.3 Payload Format Indicator
public var isUTF8EncodedData: Bool = true
/// 3.1.3.2.2 Will Delay Interval
public var willDelayInterval: UInt32? = 0
/// 3.1.3.2.4 Message Expiry Interval
public var willExpiryInterval: UInt32? = .max
/// 3.1.3.2.5 Content Type
public var contentType: String?
/// 3.1.3.2.6 Response Topic
public var willResponseTopic: String?
/// 3.1.3.2.7 Correlation Data
public var willCorrelationData: [UInt8]?
/// 3.1.3.2.8 User Property
public var willUserProperty: [String: String]?
/// Return the payload as a utf8 string if possible
///
/// It will return nil if the payload is not a valid utf8 string
public var string: String? {
NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String?
}
public var properties: [UInt8] {
var properties = [UInt8]()
var retVal = [UInt8]()
/// 3.1.3.2.2 Property Length
if let willDelayInterval = self.willDelayInterval {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.willDelayInterval.rawValue, value: willDelayInterval.byteArrayLittleEndian)
}
/// 3.1.3.2.4 Message Expiry Interval
if let willExpiryInterval = self.willExpiryInterval {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.willExpiryInterval.rawValue, value: willExpiryInterval.byteArrayLittleEndian)
}
/// 3.1.3.2.3 Payload Format Indicator
if isUTF8EncodedData {
properties += [1, 1]
} else {
properties += [1, 0]
}
/// 3.1.3.2.5 Content Type
if var contentType = self.contentType {
if isUTF8EncodedData {
contentType = contentType.stringUTF8
}
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.contentType.rawValue, value: contentType.bytesWithLength)
}
/// 3.1.3.2.6 Response Topic
if var willResponseTopic = self.willResponseTopic {
if isUTF8EncodedData {
willResponseTopic = willResponseTopic.stringUTF8
}
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.responseTopic.rawValue, value: willResponseTopic.bytesWithLength)
}
/// 3.1.3.2.7 Correlation Data
if let willCorrelationData = self.willCorrelationData {
let buff = UInt16(willCorrelationData.count).hlBytes + willCorrelationData
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.correlationData.rawValue, value: buff)
}
/// 3.1.3.2.8 User Property
if let willUserProperty = self.willUserProperty {
willUserProperty.forEach { element in
properties.append(UInt8(CocoaMQTTPropertyName.userProperty.rawValue))
if isUTF8EncodedData {
let key = element.key.stringUTF8
properties += key .bytesWithLength
let value = element.value.stringUTF8
properties += value.bytesWithLength
} else {
properties += element.key.bytesWithLength
properties += element.value.bytesWithLength
}
}
}
retVal += properties
return retVal
}
public init(topic: String, string: String, qos: CocoaMQTTQoS = .qos1, retained: Bool = false) {
self.topic = topic
self.payload = [UInt8](string.utf8)
self.qos = qos
self.retained = retained
}
public init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos1, retained: Bool = false) {
self.topic = topic
self.payload = payload
self.qos = qos
self.retained = retained
}
public init(topic: String, payload: [String: Any], qos: CocoaMQTTQoS = .qos1, retained: Bool = false) throws {
let data = try JSONSerialization.data(withJSONObject: payload)
self.topic = topic
self.payload = [UInt8](data)
self.qos = qos
self.retained = retained
}
}
extension CocoaMQTT5Message {
public override var description: String {
return "CocoaMQTT5Message(topic: \(topic), qos: \(qos), payload: \(payload.summary))"
}
}
// For test
extension CocoaMQTT5Message {
var t_pub_frame: FramePublish {
var frame = FramePublish(topic: topic, payload: payload, qos: qos, msgid: 0)
frame.retained = retained
frame.dup = duplicated
return frame
}
}

View File

@ -0,0 +1,353 @@
//
// CocoaMQTTDeliver.swift
// CocoaMQTT
//
// Created by HJianBo on 2019/5/2.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
import Dispatch
protocol CocoaMQTTDeliverProtocol: AnyObject {
var delegateQueue: DispatchQueue { get set }
func deliver(_ deliver: CocoaMQTTDeliver, wantToSend frame: Frame)
}
private struct InflightFrame {
/// The infligth frame maybe a `FramePublish` or `FramePubRel`
var frame: Frame
/// Monotonic time (Dispatch uptime) at which this frame should be retried next.
var nextRetryAtUptimeNs: UInt64
}
extension Array where Element == InflightFrame {
func filterMap(isIncluded: (Element) -> (Bool, Element)) -> [Element] {
var tmp = [Element]()
for e in self {
let res = isIncluded(e)
if res.0 {
tmp.append(res.1)
}
}
return tmp
}
}
// CocoaMQTTDeliver
class CocoaMQTTDeliver: NSObject {
/// The dispatch queue is used by delivering frames in serially
private var deliverQueue = DispatchQueue.init(label: "deliver.cocoamqtt.emqx", qos: .default)
weak var delegate: CocoaMQTTDeliverProtocol?
fileprivate var inflight = [InflightFrame]()
fileprivate var mqueue = [Frame]()
var mqueueSize: UInt = 1000
var inflightWindowSize: UInt = 10
/// Retry time interval millisecond
var retryTimeInterval: Double = 5000
private var awaitingTimer: CocoaMQTTTimer?
var isQueueEmpty: Bool { mqueue.isEmpty }
var isQueueFull: Bool { mqueue.count >= mqueueSize }
var isInflightFull: Bool { inflight.count >= inflightWindowSize }
var isInflightEmpty: Bool { inflight.isEmpty }
var storage: CocoaMQTTStorage?
func recoverSessionBy(_ storage: CocoaMQTTStorage) {
let frames = storage.readAll()
// Sync to push the frame to mqueue for avoiding overcommit
deliverQueue.sync {
self.storage = storage
for f in frames {
mqueue.append(f)
}
if !frames.isEmpty {
printInfo("Deliver recover \(frames.count) msgs")
printDebug("Recover message \(frames)")
}
}
guard !frames.isEmpty else {
return
}
deliverQueue.async { [weak self] in
guard let self = self else { return }
self.tryTransport()
}
}
/// Add a FramePublish to the message queue to wait for sending
///
/// return false means the frame is rejected because of the buffer is full
func add(_ frame: FramePublish) -> Bool {
guard !isQueueFull else {
printError("Sending buffer is full, frame \(frame) has been rejected to add.")
return false
}
// Sync to push the frame to mqueue for avoiding overcommit
deliverQueue.sync {
mqueue.append(frame)
_ = storage?.write(frame)
}
deliverQueue.async { [weak self] in
guard let self = self else { return }
self.tryTransport()
}
return true
}
/// Acknowledge a PUBLISH/PUBREL by msgid
func ack(by frame: Frame) {
let msgid: UInt16
if let puback = frame as? FramePubAck {
msgid = puback.msgid
} else if let pubrec = frame as? FramePubRec {
msgid = pubrec.msgid
} else if let pubcom = frame as? FramePubComp {
msgid = pubcom.msgid
} else {
return
}
let ackType = frame.type
let shouldRemoveFromStorage = frame is FramePubAck || frame is FramePubComp
let ackFrameDescription = String(describing: frame)
deliverQueue.async { [weak self] in
guard let self = self else { return }
let acked = self.ackInflightFrame(withMsgid: msgid, type: ackType)
if acked.count == 0 {
printWarning("Acknowledge by \(ackFrameDescription), but not found in inflight window")
} else {
// TODO: ACK DONT DELETE PUBREL
for f in acked where shouldRemoveFromStorage {
self.storage?.remove(f)
}
printDebug("Acknowledge frame id \(msgid) success, acked: \(acked)")
self.tryTransport()
}
}
}
/// Clean Inflight content to prevent message blocked, when next connection established
///
/// !!Warning: it's a temporary method for hotfix #221
func cleanAll() {
deliverQueue.sync { [weak self] in
guard let self = self else { return }
self.mqueue.removeAll()
self.inflight.removeAll()
}
}
}
// MARK: Private Funcs
extension CocoaMQTTDeliver {
// try transport a frame from mqueue to inflight
private func tryTransport() {
if isQueueEmpty || isInflightFull { return }
// take out the earliest frame
if mqueue.isEmpty { return }
let frame = mqueue.remove(at: 0)
deliver(frame)
// keep trying after a transport
self.tryTransport()
}
/// Try to deliver a frame
private func deliver(_ frame: Frame) {
if frame.qos == .qos0 {
// Send Qos0 message, whatever the in-flight queue is full
// TODO: A retrict deliver mode is need?
sendfun(frame)
} else {
sendfun(frame)
let nowUptimeNs = DispatchTime.now().uptimeNanoseconds
inflight.append(InflightFrame(frame: frame, nextRetryAtUptimeNs: nextRetryDeadline(from: nowUptimeNs)))
// Start a retry timer for resending it if it not receive PUBACK or PUBREC
if awaitingTimer == nil {
awaitingTimer = CocoaMQTTTimer.every(retryTimeInterval / 1000.0, name: "awaitingTimer") { [weak self] in
guard let self = self else { return }
self.deliverQueue.async {
self.redeliver()
}
}
}
}
}
/// Attempt to redeliver in-flight messages
private func redeliver(nowUptimeNs: UInt64 = DispatchTime.now().uptimeNanoseconds) {
if isInflightEmpty {
// Revoke the awaiting timer
awaitingTimer = nil
return
}
for (idx, frame) in inflight.enumerated() where nowUptimeNs >= frame.nextRetryAtUptimeNs {
var duplicatedFrame = frame
duplicatedFrame.frame.dup = true
duplicatedFrame.nextRetryAtUptimeNs = nextRetryDeadline(after: frame.nextRetryAtUptimeNs, nowUptimeNs: nowUptimeNs)
inflight[idx] = duplicatedFrame
printInfo("Re-delivery frame \(duplicatedFrame.frame)")
sendfun(duplicatedFrame.frame)
}
}
private func retryIntervalNanoseconds() -> UInt64 {
let intervalNs = retryTimeInterval * 1_000_000
guard intervalNs.isFinite, intervalNs > 0 else {
return 1
}
if intervalNs >= Double(UInt64.max) {
return UInt64.max
}
return UInt64(intervalNs.rounded())
}
private func nextRetryDeadline(from nowUptimeNs: UInt64) -> UInt64 {
let (nextDeadline, overflow) = nowUptimeNs.addingReportingOverflow(retryIntervalNanoseconds())
return overflow ? UInt64.max : nextDeadline
}
private func nextRetryDeadline(after currentDeadline: UInt64, nowUptimeNs: UInt64) -> UInt64 {
let intervalNs = retryIntervalNanoseconds()
guard nowUptimeNs >= currentDeadline else {
return currentDeadline
}
let missedIntervals = ((nowUptimeNs - currentDeadline) / intervalNs) + 1
let (advance, multiplyOverflow) = intervalNs.multipliedReportingOverflow(by: missedIntervals)
if multiplyOverflow {
return UInt64.max
}
let (nextDeadline, addOverflow) = currentDeadline.addingReportingOverflow(advance)
return addOverflow ? UInt64.max : nextDeadline
}
@discardableResult
private func ackInflightFrame(withMsgid msgid: UInt16, type: FrameType) -> [Frame] {
var ackedFrames = [Frame]()
inflight = inflight.filterMap { frame in
// -- ACK for PUBLISH
if let publish = frame.frame as? FramePublish,
publish.msgid == msgid {
if publish.qos == .qos2 && type == .pubrec { // -- Replace PUBLISH with PUBREL
let pubrel = FramePubRel(msgid: publish.msgid)
var nframe = frame
nframe.frame = pubrel
nframe.nextRetryAtUptimeNs = nextRetryDeadline(from: DispatchTime.now().uptimeNanoseconds)
_ = storage?.write(pubrel)
sendfun(pubrel)
ackedFrames.append(publish)
return (true, nframe)
} else if publish.qos == .qos1 && type == .puback {
ackedFrames.append(publish)
return (false, frame)
}
}
// -- ACK for PUBREL
if let pubrel = frame.frame as? FramePubRel,
pubrel.msgid == msgid && type == .pubcomp {
ackedFrames.append(pubrel)
return (false, frame)
}
return (true, frame)
}
return ackedFrames
}
private func sendfun(_ frame: Frame) {
guard let delegate = self.delegate else {
printError("The deliver delegate is nil!!! the frame will be drop: \(frame)")
return
}
if frame.qos == .qos0 {
if let p = frame as? FramePublish { storage?.remove(p) }
}
delegate.delegateQueue.async {
delegate.deliver(self, wantToSend: frame)
}
}
}
// For tests
extension CocoaMQTTDeliver {
func t_inflightFrames() -> [Frame] {
var frames = [Frame]()
for f in inflight {
frames.append(f.frame)
}
return frames
}
func t_queuedFrames() -> [Frame] {
return mqueue
}
@discardableResult
func t_setInflightNextRetryTime(_ nextRetryAtUptimeNs: UInt64, forMsgid msgid: UInt16) -> Bool {
return deliverQueue.sync {
for idx in inflight.indices {
if let publish = inflight[idx].frame as? FramePublish, publish.msgid == msgid {
inflight[idx].nextRetryAtUptimeNs = nextRetryAtUptimeNs
return true
}
if let pubrel = inflight[idx].frame as? FramePubRel, pubrel.msgid == msgid {
inflight[idx].nextRetryAtUptimeNs = nextRetryAtUptimeNs
return true
}
}
return false
}
}
func t_retryIntervalNanoseconds() -> UInt64 {
return deliverQueue.sync {
retryIntervalNanoseconds()
}
}
func t_redeliver(atUptimeNanoseconds uptimeNs: UInt64) {
deliverQueue.sync {
self.redeliver(nowUptimeNs: uptimeNs)
}
}
}

View File

@ -0,0 +1,71 @@
//
// CocoaMQTTLogger.swift
// CocoaMQTT
//
// Created by HJianBo on 2019/5/2.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
// Convenience functions
func printDebug(_ message: String) {
CocoaMQTTLogger.logger.debug(message)
}
func printInfo(_ message: String) {
CocoaMQTTLogger.logger.info(message)
}
func printWarning(_ message: String) {
CocoaMQTTLogger.logger.warning(message)
}
func printError(_ message: String) {
CocoaMQTTLogger.logger.error(message)
}
// Enum log levels
public enum CocoaMQTTLoggerLevel: Int {
case debug = 0, info, warning, error, off
}
open class CocoaMQTTLogger: NSObject {
// Singleton
// Keep mutable global logger for backward compatibility.
// Accesses are intentionally marked as unsafe-isolated for Swift 6 readiness.
#if swift(>=6)
public nonisolated(unsafe) static var logger = CocoaMQTTLogger()
#else
public static var logger = CocoaMQTTLogger()
#endif
public override init() { super.init() }
// min level
@ConcurrentAtomic(wrappedValue: .warning, label: "CocoaMQTTLogger.minLevel")
public var minLevel: CocoaMQTTLoggerLevel
// logs
open func log(level: CocoaMQTTLoggerLevel, message: String) {
guard level.rawValue >= minLevel.rawValue else { return }
print("CocoaMQTT(\(level)): \(message)")
}
func debug(_ message: String) {
log(level: .debug, message: message)
}
func info(_ message: String) {
log(level: .info, message: message)
}
func warning(_ message: String) {
log(level: .warning, message: message)
}
func error(_ message: String) {
log(level: .error, message: message)
}
}

View File

@ -0,0 +1,66 @@
//
// CocoaMQTTMessage.swift
// CocoaMQTT
//
// Created by Feng Lee<feng@eqmtt.io> on 14/8/3.
// Copyright (c) 2015 emqx.io. All rights reserved.
//
import Foundation
/// MQTT Message
public class CocoaMQTTMessage: NSObject {
public var qos = CocoaMQTTQoS.qos1
public var topic: String
public var payload: [UInt8]
public var retained = false
/// The `duplicated` property show that this message maybe has be received before
///
/// - note: Readonly property
public var duplicated = false
/// Return the payload as a utf8 string if possible
///
/// It will return nil if the payload is not a valid utf8 string
public var string: String? {
NSString(bytes: payload, length: payload.count, encoding: String.Encoding.utf8.rawValue) as String?
}
public init(topic: String, string: String, qos: CocoaMQTTQoS = .qos1, retained: Bool = false) {
self.topic = topic
self.payload = [UInt8](string.utf8)
self.qos = qos
self.retained = retained
}
public init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos1, retained: Bool = false) {
self.topic = topic
self.payload = payload
self.qos = qos
self.retained = retained
}
}
extension CocoaMQTTMessage {
public override var description: String {
return "CocoaMQTTMessage(topic: \(topic), qos: \(qos), payload: \(payload.summary))"
}
}
// For test
extension CocoaMQTTMessage {
var t_pub_frame: FramePublish {
var frame = FramePublish(topic: topic, payload: payload, qos: qos, msgid: 0)
frame.retained = retained
frame.dup = duplicated
return frame
}
}

View File

@ -0,0 +1,189 @@
//
// CocoaMQTTPropertyType.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/6.
//
import Foundation
public enum CocoaMQTTPropertyName: UInt8 {
case payloadFormatIndicator = 0x01
case willExpiryInterval = 0x02
case contentType = 0x03
case responseTopic = 0x08
case correlationData = 0x09
case subscriptionIdentifier = 0x0B
case sessionExpiryInterval = 0x11
case assignedClientIdentifier = 0x12
case serverKeepAlive = 0x13
case authenticationMethod = 0x15
case authenticationData = 0x16
case requestProblemInformation = 0x17
case willDelayInterval = 0x18
case requestResponseInformation = 0x19
case responseInformation = 0x1A
case serverReference = 0x1C
case reasonString = 0x1F
case receiveMaximum = 0x21
case topicAliasMaximum = 0x22
case topicAlias = 0x23
case maximumQoS = 0x24
case retainAvailable = 0x25
case userProperty = 0x26
case maximumPacketSize = 0x27
case wildcardSubscriptionAvailable = 0x28
case subscriptionIdentifiersAvailable = 0x29
case sharedSubscriptionAvailable = 0x2A
}
public enum formatInt: Int {
case formatUint8 = 0x11
case formatUint16 = 0x12
case formatUint32 = 0x14
case formatSint8 = 0x21
case formatSint16 = 0x22
case formatSint32 = 0x24
}
func getMQTTPropertyData(type: UInt8, value: [UInt8]) -> [UInt8] {
var properties = [UInt8]()
properties.append(UInt8(type))
properties += value
return properties
}
func getMQTTPropertyLength(type: UInt8, value: [UInt8]) -> [UInt8] {
var properties = [UInt8]()
properties.append(UInt8(type))
properties += value
return properties
}
func integerCompute(data: [UInt8], formatType: Int, offset: Int) -> (res: Int, newOffset: Int)? {
switch formatType {
case formatInt.formatUint8.rawValue:
return (unsignedByteToInt(data: data[offset]), offset + 1)
case formatInt.formatUint16.rawValue:
return (unsignedBytesToInt(data0: data[offset], data1: data[offset + 1]), offset + 2)
case formatInt.formatUint32.rawValue:
return (unsignedBytesToInt(data0: data[offset], data1: data[offset + 1], data2: data[offset + 2], data3: data[offset + 3]), offset + 4)
case formatInt.formatSint8.rawValue:
return (unsignedToSigned(unsign: unsignedByteToInt(data: data[offset]), size: 8), offset + 1)
case formatInt.formatSint16.rawValue:
return (unsignedToSigned(unsign: unsignedBytesToInt(data0: data[offset], data1: data[offset + 1]), size: 16), offset + 2)
case formatInt.formatSint32.rawValue:
return (unsignedToSigned(unsign: unsignedBytesToInt(data0: data[offset], data1: data[offset + 1], data2: data[offset + 2], data3: data[offset + 3]), size: 32), offset + 4)
default:
printDebug("integerCompute nothing")
}
return nil
}
func unsignedByteToInt(data: UInt8) -> (Int) {
return (Int)(data & 0xFF)
}
func unsignedBytesToInt(data0: UInt8, data1: UInt8) -> (Int) {
return (unsignedByteToInt(data: data0) << 8) + unsignedByteToInt(data: data1)
}
func unsignedBytesToInt(data0: UInt8, data1: UInt8, data2: UInt8, data3: UInt8) -> (Int) {
return unsignedByteToInt(data: data3) + (unsignedByteToInt(data: data2) << 8) + (unsignedByteToInt(data: data1) << 16) + (unsignedByteToInt(data: data0) << 24)
}
func unsignedToSigned(unsign: NSInteger, size: NSInteger) -> (Int) {
var res = unsign
if (res & (1 << size-1)) != 0 {
res = -1 * ((1 << size-1) - (res & ((1 << size-1) - 1)))
}
return res
}
func unsignedByteToString(data: [UInt8], offset: Int) -> (resStr: String, newOffset: Int)? {
var newOffset = offset
if offset + 1 > data.count {
return nil
}
var length = 0
let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset)
length = comRes!.res
newOffset = comRes!.newOffset
var stringData = Data()
for _ in 0 ..< length {
stringData.append(data[newOffset])
newOffset += 1
}
guard let res = String(data: stringData, encoding: .utf8) else {
return nil
}
return (res, newOffset)
}
func unsignedByteToBinary(data: [UInt8], offset: Int) -> (resStr: [UInt8], newOffset: Int)? {
var newOffset = offset
if offset + 1 > data.count {
return nil
}
var length = 0
let comRes = integerCompute(data: data, formatType: formatInt.formatUint16.rawValue, offset: newOffset)
length = comRes!.res
newOffset = comRes!.newOffset
var res = [UInt8]()
for _ in 0 ..< length {
res.append(data[newOffset])
newOffset += 1
}
return (res, newOffset)
}
// 1.5.5 Variable Byte Integer
// The Variable Byte Integer is encoded using an encoding scheme which uses a single byte for values up to 127. Larger values are handled as follows. The least significant seven bits of each byte encode the data, and the most significant bit is used to indicate whether there are bytes following in the representation. Thus, each byte encodes 128 values and a "continuation bit". The maximum number of bytes in the Variable Byte Integer field is four. The encoded value MUST use the minimum number of bytes necessary to represent the value [MQTT-1.5.5-1]. This is shown in Table 11 Size of Variable Byte Integer.
func decodeVariableByteInteger(data: [UInt8], offset: Int) -> (res: Int, newOffset: Int) {
var newOffset = offset
var count = 0
var res: Int = 0
while newOffset < data.count {
let newValue = Int(data[newOffset] & 0x7f) << count
res += newValue
if (data[newOffset] & 0x80) == 0 || count >= 21 {
newOffset += 1
break
}
newOffset += 1
count += 7
}
return (res, newOffset)
}
func beVariableByteInteger(length: Int) -> [UInt8] {
var res = [UInt8]()
var tmpLen: Int = length
repeat {
var d: UInt8 = UInt8(tmpLen % 128)
tmpLen /= 128
if tmpLen > 0 {
d |= 0x80
}
res.append(d)
} while(tmpLen > 0)
return res
}
func beVariableByteInteger(_ data: UInt32) -> [UInt8]? {
if data > 0x0fffffff {
return nil
}
return beVariableByteInteger(length: Int(data))
}

View File

@ -0,0 +1,220 @@
//
// CocoaMQTTReader.swift
// CocoaMQTT
//
// Created by HJianBo on 2019/5/21.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// Read tag for AsyncSocket
enum CocoaMQTTReadTag: Int {
case header = 0
case length
case payload
}
///
protocol CocoaMQTTReaderDelegate: AnyObject {
func didReceive(_ reader: CocoaMQTTReader, connack: FrameConnAck)
func didReceive(_ reader: CocoaMQTTReader, publish: FramePublish)
func didReceive(_ reader: CocoaMQTTReader, puback: FramePubAck)
func didReceive(_ reader: CocoaMQTTReader, pubrec: FramePubRec)
func didReceive(_ reader: CocoaMQTTReader, pubrel: FramePubRel)
func didReceive(_ reader: CocoaMQTTReader, pubcomp: FramePubComp)
func didReceive(_ reader: CocoaMQTTReader, suback: FrameSubAck)
func didReceive(_ reader: CocoaMQTTReader, unsuback: FrameUnsubAck)
func didReceive(_ reader: CocoaMQTTReader, pingresp: FramePingResp)
func didReceive(_ reader: CocoaMQTTReader, disconnect: FrameDisconnect)
func didReceive(_ reader: CocoaMQTTReader, auth: FrameAuth)
}
class CocoaMQTTReader {
private var socket: CocoaMQTTSocketProtocol
private weak var delegate: CocoaMQTTReaderDelegate?
private let timeout: TimeInterval = 30_000
/* -- Reader states -- */
private var header: UInt8 = 0
private var length: UInt = 0
private var data: [UInt8] = []
private var multiply = 1
/* -- Reader states -- */
init(socket: CocoaMQTTSocketProtocol, delegate: CocoaMQTTReaderDelegate?) {
self.socket = socket
self.delegate = delegate
}
func start() {
readHeader()
}
func headerReady(_ header: UInt8) {
self.header = header
readLength()
}
func lengthReady(_ byte: UInt8) {
length += (UInt)((Int)(byte & 127) * multiply)
// done
if byte & 0x80 == 0 {
if length == 0 {
frameReady()
} else {
readPayload()
}
// more
} else {
let result = multiply.multipliedReportingOverflow(by: 128)
if !result.overflow {
multiply = result.partialValue
} else {
reset()
}
readLength()
}
}
func payloadReady(_ data: Data) {
self.data = [UInt8](repeating: 0, count: data.count)
data.copyBytes(to: &(self.data), count: data.count)
frameReady()
}
private func readHeader() {
reset()
socket.readData(toLength: 1, withTimeout: -1, tag: CocoaMQTTReadTag.header.rawValue)
}
private func readLength() {
socket.readData(toLength: 1, withTimeout: timeout, tag: CocoaMQTTReadTag.length.rawValue)
}
private func readPayload() {
socket.readData(toLength: length, withTimeout: timeout, tag: CocoaMQTTReadTag.payload.rawValue)
}
private func frameReady() {
guard let frameType = FrameType(rawValue: UInt8(header & 0xF0)) else {
protocolError("Received unknown frame type, header: \(header), data:\(data)")
return
}
// XXX: stupid implement
switch frameType {
case .connack:
guard let connack = FrameConnAck(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, connack: connack)
case .publish:
guard let publish = FramePublish(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, publish: publish)
case .puback:
guard let puback = FramePubAck(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, puback: puback)
case .pubrec:
guard let pubrec = FramePubRec(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, pubrec: pubrec)
case .pubrel:
guard let pubrel = FramePubRel(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, pubrel: pubrel)
case .pubcomp:
guard let pubcomp = FramePubComp(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, pubcomp: pubcomp)
case .suback:
guard let frame = FrameSubAck(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, suback: frame)
case .unsuback:
guard let frame = FrameUnsubAck(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, unsuback: frame)
case .pingresp:
guard let frame = FramePingResp(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, pingresp: frame)
case .disconnect:
guard isMQTT5ProtocolVersion() else {
protocolError("Reader received MQTT5-only frame \(frameType) in non-MQTT5 mode, data: \(data)")
return
}
guard let frame = FrameDisconnect(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, disconnect: frame)
case .auth:
guard isMQTT5ProtocolVersion() else {
protocolError("Reader received MQTT5-only frame \(frameType) in non-MQTT5 mode, data: \(data)")
return
}
guard let frame = FrameAuth(packetFixedHeaderType: header, bytes: data) else {
protocolError("Reader parse \(frameType) failed, data: \(data)")
return
}
delegate?.didReceive(self, auth: frame)
default:
protocolError("Received unsupported frame type \(frameType), data: \(data)")
return
}
readHeader()
}
private func protocolError(_ reason: String) {
printError(reason)
socket.disconnect()
}
private func isMQTT5ProtocolVersion() -> Bool {
return CocoaMQTTStorage()?.queryMQTTVersion() == "5.0"
}
private func reset() {
length = 0
multiply = 1
header = 0
data = []
}
}

View File

@ -0,0 +1,141 @@
//
// CocoaMQTTReasonCode.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/4.
//
import Foundation
@objc public enum CocoaMQTTAUTHReasonCode: UInt8 {
case success = 0x00
case continueAuthentication = 0x18
case ReAuthenticate = 0x19
}
@objc public enum CocoaMQTTCONNACKReasonCode: UInt8 {
case success = 0x00
case unspecifiedError = 0x80
case malformedPacket = 0x81
case protocolError = 0x82
case implementationSpecificError = 0x83
case unsupportedProtocolVersion = 0x84
case clientIdentifierNotValid = 0x85
case badUsernameOrPassword = 0x86
case notAuthorized = 0x87
case serverUnavailable = 0x88
case serverBusy = 0x89
case banned = 0x8A
case badAuthenticationMethod = 0x8C
case topicNameInvalid = 0x90
case packetTooLarge = 0x95
case quotaExceeded = 0x97
case payloadFormatInvalid = 0x99
case retainNotSupported = 0x9A
case qosNotSupported = 0x9B
case useAnotherServer = 0x9C
case serverMoved = 0x9D
case connectionRateExceeded = 0x9F
}
@objc public enum CocoaMQTTDISCONNECTReasonCode: UInt8 {
case normalDisconnection = 0x00
case disconnectWithWillMessage = 0x04
case unspecifiedError = 0x80
case malformedPacket = 0x81
case protocolError = 0x82
case implementationSpecificError = 0x83
case notAuthorized = 0x87
case serverBusy = 0x89
case serverShuttingDown = 0x8B
case keepAliveTimeout = 0x8D
case sessionTakenOver = 0x8E
case topicFilterInvalid = 0x8F
case topicNameInvalid = 0x90
case receiveMaximumExceeded = 0x93
case topicAliasInvalid = 0x94
case packetTooLarge = 0x95
case messageRateTooHigh = 0x96
case quotaExceeded = 0x97
case administrativeAction = 0x98
case payloadFormatInvalid = 0x99
case retainNotSupported = 0x9A
case qosNotSupported = 0x9B
case useAnotherServer = 0x9C
case serverMoved = 0x9D
case sharedSubscriptionsNotSupported = 0x9E
case connectionRateExceeded = 0x9F
case maximumConnectTime = 0xA0
case subscriptionIdentifiersNotSupported = 0xA1
case wildcardSubscriptionsNotSupported = 0xA2
}
@objc public enum CocoaMQTTPUBACKReasonCode: UInt8 {
case success = 0x00
case noMatchingSubscribers = 0x10
case unspecifiedError = 0x80
case implementationSpecificError = 0x83
case notAuthorized = 0x87
case topicNameInvalid = 0x90
case packetIdentifierInUse = 0x91
case quotaExceeded = 0x97
case payloadFormatInvalid = 0x99
}
@objc public enum CocoaMQTTPUBCOMPReasonCode: UInt8 {
case success = 0x00
case packetIdentifierNotFound = 0x92
}
@objc public enum CocoaMQTTPUBRECReasonCode: UInt8 {
case success = 0x00
case noMatchingSubscribers = 0x10
case unspecifiedError = 0x80
case implementationSpecificError = 0x83
case notAuthorized = 0x87
case topicNameInvalid = 0x90
case packetIdentifierInUse = 0x91
case quotaExceeded = 0x97
case payloadFormatInvalid = 0x99
}
@objc public enum CocoaMQTTPUBRELReasonCode: UInt8 {
case success = 0x00
case packetIdentifierNotFound = 0x92
}
@objc public enum CocoaMQTTSUBACKReasonCode: UInt8 {
case grantedQoS0 = 0x00
case grantedQoS1 = 0x01
case grantedQoS2 = 0x02
case unspecifiedError = 0x80
case implementationSpecificError = 0x83
case notAuthorized = 0x87
case topicFilterInvalid = 0x8F
case packetIdentifierInUse = 0x91
case quotaExceeded = 0x97
case sharedSubscriptionsNotSupported = 0x9E
case subscriptionIdentifiersNotSupported = 0xA1
case wildcardSubscriptionsNotSupported = 0xA2
}
@objc public enum CocoaMQTTUNSUBACKReasonCode: UInt8 {
case success = 0x00
case noSubscriptionExisted = 0x11
case unspecifiedError = 0x80
case implementationSpecificError = 0x83
case notAuthorized = 0x87
case topicFilterInvalid = 0x8F
case packetIdentifierInUse = 0x91
}
@objc public enum CocoaRetainHandlingOption: UInt8 {
case sendOnSubscribe = 0
case sendOnlyWhenSubscribeIsNew = 1
case none = 2
}
@objc public enum PayloadFormatIndicator: UInt8 {
case unspecified = 0x00
case utf8 = 0x01
}

View File

@ -0,0 +1,136 @@
//
// CocoaMQTTSocket.swift
// CocoaMQTT
//
// Created by Cyrus Ingraham on 12/13/19.
//
import Foundation
import MqttCocoaAsyncSocket
// MARK: - Interfaces
public protocol CocoaMQTTSocketDelegate: AnyObject {
func socketConnected(_ socket: CocoaMQTTSocketProtocol)
func socket(_ socket: CocoaMQTTSocketProtocol, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void)
func socketUrlSession(_ socket: CocoaMQTTSocketProtocol, didReceiveTrust trust: SecTrust, didReceiveChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
func socket(_ socket: CocoaMQTTSocketProtocol, didWriteDataWithTag tag: Int)
func socket(_ socket: CocoaMQTTSocketProtocol, didRead data: Data, withTag tag: Int)
func socketDidDisconnect(_ socket: CocoaMQTTSocketProtocol, withError err: Error?)
}
public protocol CocoaMQTTSocketProtocol {
var enableSSL: Bool { get set }
func setDelegate(_ theDelegate: CocoaMQTTSocketDelegate?, delegateQueue: DispatchQueue?)
func connect(toHost host: String, onPort port: UInt16) throws
func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws
func disconnect()
func readData(toLength length: UInt, withTimeout timeout: TimeInterval, tag: Int)
func write(_ data: Data, withTimeout timeout: TimeInterval, tag: Int)
}
// MARK: - CocoaMQTTSocket
public class CocoaMQTTSocket: NSObject {
public var backgroundOnSocket = true
public var enableSSL = false
///
public var sslSettings: [String: NSObject]?
/// Allow self-signed ca certificate.
///
/// Default is false
public var allowUntrustCACertificate = false
fileprivate let reference = MGCDAsyncSocket()
fileprivate weak var delegate: CocoaMQTTSocketDelegate?
public override init() { super.init() }
}
extension CocoaMQTTSocket: CocoaMQTTSocketProtocol {
public func setDelegate(_ theDelegate: CocoaMQTTSocketDelegate?, delegateQueue: DispatchQueue?) {
delegate = theDelegate
reference.setDelegate((delegate != nil ? self : nil), delegateQueue: delegateQueue)
}
public func connect(toHost host: String, onPort port: UInt16) throws {
try connect(toHost: host, onPort: port, withTimeout: -1)
}
public func connect(toHost host: String, onPort port: UInt16, withTimeout timeout: TimeInterval) throws {
try reference.connect(toHost: host, onPort: port, withTimeout: timeout)
}
public func disconnect() {
reference.disconnect()
}
public func readData(toLength length: UInt, withTimeout timeout: TimeInterval, tag: Int) {
reference.readData(toLength: length, withTimeout: timeout, tag: tag)
}
public func write(_ data: Data, withTimeout timeout: TimeInterval, tag: Int) {
reference.write(data, withTimeout: timeout, tag: tag)
}
}
extension CocoaMQTTSocket: MGCDAsyncSocketDelegate {
public func socket(_ sock: MGCDAsyncSocket, didConnectToHost host: String, port: UInt16) {
printInfo("Connected to \(host) : \(port)")
#if os(iOS)
if backgroundOnSocket {
sock.perform {
guard sock.enableBackgroundingOnSocket() else {
printWarning("Enable backgrounding socket failed, please check related permissions")
return
}
printInfo("Enable backgrounding socket successfully")
}
}
#endif
if enableSSL {
var setting = sslSettings ?? [:]
if allowUntrustCACertificate {
setting[MGCDAsyncSocketManuallyEvaluateTrust as String] = NSNumber(value: true)
}
sock.startTLS(setting)
} else {
delegate?.socketConnected(self)
}
}
public func socket(_ sock: MGCDAsyncSocket, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Swift.Void) {
if let theDelegate = delegate {
theDelegate.socket(self, didReceive: trust, completionHandler: completionHandler)
} else {
completionHandler(false)
}
}
public func socketDidSecure(_ sock: MGCDAsyncSocket) {
printDebug("socket did secure")
delegate?.socketConnected(self)
}
public func socket(_ sock: MGCDAsyncSocket, didWriteDataWithTag tag: Int) {
printDebug("socket wrote data \(tag)")
delegate?.socket(self, didWriteDataWithTag: tag)
}
public func socket(_ sock: MGCDAsyncSocket, didRead data: Data, withTag tag: Int) {
delegate?.socket(self, didRead: data, withTag: tag)
}
public func socketDidDisconnect(_ sock: MGCDAsyncSocket, withError err: Error?) {
printDebug("socket disconnected")
delegate?.socketDidDisconnect(self, withError: err)
}
}

View File

@ -0,0 +1,161 @@
//
// CocoaMQTTStorage.swift
// CocoaMQTT
//
// Created by JianBo on 2019/10/6.
// Copyright © 2019 emqtt.io. All rights reserved.
//
import Foundation
protocol CocoaMQTTStorageProtocol {
var clientId: String { get set }
init?(by clientId: String)
func write(_ frame: FramePublish) -> Bool
func write(_ frame: FramePubRel) -> Bool
func remove(_ frame: FramePublish)
func remove(_ frame: FramePubRel)
func synchronize() -> Bool
/// Read all stored messages by saving order
func readAll() -> [Frame]
}
final class CocoaMQTTStorage: CocoaMQTTStorageProtocol {
var clientId: String = ""
var userDefault: UserDefaults = UserDefaults()
var versionDefault: UserDefaults = UserDefaults()
init?() {
versionDefault = UserDefaults()
}
init?(by clientId: String) {
guard let userDefault = UserDefaults(suiteName: CocoaMQTTStorage.name(clientId)) else {
return nil
}
self.clientId = clientId
self.userDefault = userDefault
}
deinit {
userDefault.synchronize()
versionDefault.synchronize()
}
func setMQTTVersion(_ version: String) {
versionDefault.set(version, forKey: "cocoamqtt.emqx.version")
}
func queryMQTTVersion() -> String {
return versionDefault.string(forKey: "cocoamqtt.emqx.version") ?? "3.1.1"
}
func write(_ frame: FramePublish) -> Bool {
guard frame.qos > .qos0 else {
return false
}
userDefault.set(frame.bytes(version: queryMQTTVersion()), forKey: key(frame.msgid))
return true
}
func write(_ frame: FramePubRel) -> Bool {
userDefault.set(frame.bytes( version: queryMQTTVersion()), forKey: key(frame.msgid))
return true
}
func remove(_ frame: FramePublish) {
userDefault.removeObject(forKey: key(frame.msgid))
}
func remove(_ frame: FramePubRel) {
userDefault.removeObject(forKey: key(frame.msgid))
}
func remove(_ frame: Frame) {
if let pub = frame as? FramePublish {
userDefault.removeObject(forKey: key(pub.msgid))
} else if let rel = frame as? FramePubRel {
userDefault.removeObject(forKey: key(rel.msgid))
}
}
func synchronize() -> Bool {
return userDefault.synchronize()
}
func readAll() -> [Frame] {
return __read(needDelete: false)
}
func takeAll() -> [Frame] {
return __read(needDelete: true)
}
private func key(_ msgid: UInt16) -> String {
return "\(msgid)"
}
private static func name(_ clientId: String) -> String {
return "cocomqtt-\(clientId)"
}
private func parse(_ bytes: [UInt8]) -> (UInt8, [UInt8])? {
// FramePubRel is 4 bytes long
guard bytes.count > 3 else {
return nil
}
// bytes 1..<5 may be 'Remaining Length'
for i in 1 ..< min(5, bytes.count) where (bytes[i] & 0x80) == 0 {
return (bytes[0], Array(bytes.suffix(from: i + 1)))
}
return nil
}
private func __read(needDelete: Bool) -> [Frame] {
var frames = [Frame]()
let allObjs = userDefault.dictionaryRepresentation().sorted { (k1, k2) in
let left = UInt16(k1.key)
let right = UInt16(k2.key)
switch (left, right) {
case let (l?, r?):
return l < r
case (_?, nil):
return true
case (nil, _?):
return false
case (nil, nil):
return k1.key < k2.key
}
}
for (k, v) in allObjs {
guard let bytes = v as? [UInt8] else { continue }
guard let parsed = parse(bytes) else { continue }
if needDelete {
userDefault.removeObject(forKey: k)
}
if let f = FramePublish(packetFixedHeaderType: parsed.0, bytes: parsed.1) {
frames.append(f)
} else if let f = FramePubRel(packetFixedHeaderType: parsed.0, bytes: parsed.1) {
frames.append(f)
}
}
return frames
}
}

110
Pods/CocoaMQTT/Source/CocoaMQTTTimer.swift generated Normal file
View File

@ -0,0 +1,110 @@
//
// CocoaMQTTTimer.swift
// CocoaMQTT
//
// Contributed by Jens(https://github.com/jmiltner)
//
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
// modeled after RepeatingTimer by Daniel Galasko: https://medium.com/@danielgalasko/a-background-repeating-timer-in-swift-412cecfd2ef9
/// RepeatingTimer mimics the API of DispatchSourceTimer but in a way that prevents
/// crashes that occur from calling resume multiple times on a timer that is
/// already resumed (noted by https://github.com/SiftScience/sift-ios/issues/52)
class CocoaMQTTTimer {
let timeInterval: TimeInterval
let startDelay: TimeInterval
let name: String
init(delay: TimeInterval?=nil, name: String, timeInterval: TimeInterval) {
self.name = name
self.timeInterval = timeInterval
if let delay = delay {
self.startDelay = delay
} else {
self.startDelay = timeInterval
}
}
class func every(_ interval: TimeInterval, name: String, _ block: @escaping () -> Void) -> CocoaMQTTTimer {
let timer = CocoaMQTTTimer(name: name, timeInterval: interval)
timer.eventHandler = block
timer.resume()
return timer
}
@discardableResult
class func after(_ interval: TimeInterval, name: String, _ block: @escaping () -> Void) -> CocoaMQTTTimer {
let timer: CocoaMQTTTimer? = CocoaMQTTTimer(delay: interval, name: name, timeInterval: 0)
timer?.eventHandler = { [weak timer] in
block()
timer?.suspend()
timer = nil
}
timer?.resume()
return timer!
}
/// Execute the tasks concurrently on the target_queue with default QOS
private static let target_queue = DispatchQueue(label: "io.emqx.CocoaMQTT.TimerQueue", qos: .default, attributes: .concurrent)
/// Execute each timer tasks serially and use the target queue for concurrency among timers
private lazy var timer: DispatchSourceTimer = {
let queue = DispatchQueue(label: "io.emqx.CocoaMQTT." + name, target: CocoaMQTTTimer.target_queue)
let t = DispatchSource.makeTimerSource(flags: .strict, queue: queue)
t.schedule(deadline: .now() + self.startDelay, repeating: self.timeInterval > 0 ? Double(self.timeInterval) : Double.infinity)
t.setEventHandler(handler: { [weak self] in
self?.eventHandler?()
})
return t
}()
var eventHandler: (() -> Void)?
private enum State {
case suspended
case resumed
case canceled
}
private var state: State = .suspended
deinit {
timer.setEventHandler {}
timer.cancel()
/*
If the timer is suspended, calling cancel without resuming
triggers a crash. This is documented here https://forums.developer.apple.com/thread/15902
*/
resume()
eventHandler = nil
}
func resume() {
if state == .resumed {
return
}
state = .resumed
timer.resume()
}
func suspend() {
if state == .suspended {
return
}
state = .suspended
timer.suspend()
}
/// Manually cancel timer
func cancel() {
if state == .canceled {
return
}
state = .canceled
timer.cancel()
}
}

166
Pods/CocoaMQTT/Source/CocoaMQTTTypes.swift generated Normal file
View File

@ -0,0 +1,166 @@
//
// CocoaMQTTTypes.swift
// CocoaMQTT
//
// Created by HJianBo on 2019/6/9.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// Encode and Decode big-endian UInt16
extension UInt16 {
/// Most Significant Byte (MSB)
private var highByte: UInt8 {
return UInt8( (self & 0xFF00) >> 8)
}
/// Least Significant Byte (LSB)
private var lowByte: UInt8 {
return UInt8(self & 0x00FF)
}
var hlBytes: [UInt8] {
return [highByte, lowByte]
}
}
extension String {
/// String with two bytes length
var bytesWithLength: [UInt8] {
return UInt16(utf8.count).hlBytes + utf8
}
var stringUTF8: String {
let data = self.data(using: .nonLossyASCII)
return String(data: data!, encoding: .utf8) ?? ""
}
}
extension Bool {
/// Bool to bit of UInt8
var bit: UInt8 {
return self ? 1 : 0
}
/// Initial a bool with a bit
init(bit: UInt8) {
self = (bit == 0) ? false : true
}
}
extension UInt8 {
/// Read a bit value
func bitAt(_ offset: UInt8) -> UInt8 {
return (self >> offset) & 0x01
}
}
public enum CocoaMQTTError: Error {
case invalidURL
case readTimeout
case writeTimeout
@available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public enum FoundationConnection: Error {
case closed(URLSessionWebSocketTask.CloseCode)
}
}
extension Array where Element == UInt8 {
var summary: String {
if self.count <= 10 {
return "\(self)"
} else {
var descr = "[\(self[0])"
for i in self[1..<10] {
descr += ", \(i)"
}
return "\(descr), ...]"
}
}
}
extension Data {
var uint8: UInt8 {
var number: UInt8 = 0
self.copyBytes(to: &number, count: MemoryLayout<UInt8>.size)
return number
}
var uint16: UInt16 {
let i16array = self.withUnsafeBytes { $0.load(as: UInt16.self) }
return i16array
}
var uint32: UInt32 {
let i32array = self.withUnsafeBytes { $0.load(as: UInt32.self) }
return i32array
}
var uuid: NSUUID? {
var bytes = [UInt8](repeating: 0, count: self.count)
self.copyBytes(to: &bytes, count: self.count * MemoryLayout<UInt32>.size)
return NSUUID(uuidBytes: bytes)
}
var stringASCII: String? {
return NSString(data: self, encoding: String.Encoding.ascii.rawValue) as String?
}
var stringUTF8: String? {
return NSString(data: self, encoding: String.Encoding.utf8.rawValue) as String?
}
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}
func hexEncodedString(options: HexEncodingOptions = []) -> String {
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
return map { String(format: format, $0) }.joined()
}
}
extension Int {
var data: Data {
var int = self
return Data(bytes: &int, count: MemoryLayout<Int>.size)
}
}
extension UInt8 {
var data: Data {
var int = self
return Data(bytes: &int, count: MemoryLayout<UInt8>.size)
}
}
extension UInt16 {
var data: Data {
var int = self
return Data(bytes: &int, count: MemoryLayout<UInt16>.size)
}
}
extension UInt32 {
var data: Data {
var int = self
return Data(bytes: &int, count: MemoryLayout<UInt32>.size)
}
var byteArrayLittleEndian: [UInt8] {
return [
UInt8((self & 0xFF000000) >> 24),
UInt8((self & 0x00FF0000) >> 16),
UInt8((self & 0x0000FF00) >> 8),
UInt8(self & 0x000000FF)
]
}
}
extension Dictionary where Key == String, Value == String {
var userPropertyBytes: [UInt8] {
return reduce([UInt8](), { $0 + getMQTTPropertyData(type: CocoaMQTTPropertyName.userProperty.rawValue, value: $1.key.bytesWithLength + $1.value.bytesWithLength) })
}
}

215
Pods/CocoaMQTT/Source/Frame.swift generated Normal file
View File

@ -0,0 +1,215 @@
//
// Frame.swift
// CocoaMQTT
//
// Created by Feng Lee<feng@eqmtt.io> on 14/8/3.
// Copyright (c) 2015 emqx.io. All rights reserved.
//
import Foundation
/// Quality of Service levels
@objc public enum CocoaMQTTQoS: UInt8, CustomStringConvertible {
/// At most once delivery
case qos0 = 0
/// At least once delivery
case qos1
/// Exactly once delivery
case qos2
/// !!! Used SUBACK frame only
case FAILURE = 0x80
public var description: String {
switch self {
case .qos0: return "qos0"
case .qos1: return "qos1"
case .qos2: return "qos2"
case .FAILURE: return "Failure"
}
}
}
extension CocoaMQTTQoS: Comparable {
public static func < (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool {
return lhs.rawValue < rhs.rawValue
}
public static func <= (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool {
return lhs.rawValue <= rhs.rawValue
}
public static func > (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool {
return lhs.rawValue > rhs.rawValue
}
public static func >= (lhs: CocoaMQTTQoS, rhs: CocoaMQTTQoS) -> Bool {
return lhs.rawValue >= rhs.rawValue
}
}
/// MQTT Frame Type
enum FrameType: UInt8 {
case reserved = 0x00
case connect = 0x10
case connack = 0x20
case publish = 0x30
case puback = 0x40
case pubrec = 0x50
case pubrel = 0x60
case pubcomp = 0x70
case subscribe = 0x80
case suback = 0x90
case unsubscribe = 0xA0
case unsuback = 0xB0
case pingreq = 0xC0
case pingresp = 0xD0
case disconnect = 0xE0
case auth = 0xF0
}
/// The frame can be initialized with a bytes
protocol InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8])
}
/// MQTT Frame protocol
protocol Frame {
/// Each MQTT Control Packet contains a fixed header
/// MQTT 3.1.1
var packetFixedHeaderType: UInt8 {get set}
/// MQTT 5.0
func fixedHeader() -> [UInt8]
/// Some types of MQTT Control Packets contain a variable header component
/// MQTT 3.1.1
func variableHeader() -> [UInt8]
/// MQTT 5.0
func variableHeader5() -> [UInt8]
/// MQTT 5.0 The last field in the Variable Header of the CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, and AUTH packet is a set of Properties. In the CONNECT packet there is also an optional set of Properties in the Will Properties field with the Payload.
func properties() -> [UInt8]
/// Some MQTT Control Packets contain a payload as the final part of the packet
/// MQTT 3.1.1
func payload() -> [UInt8]
/// MQTT 5.0
func payload5() -> [UInt8]
/// fixedHeader + variableHeader + properties + payload
func allData() -> [UInt8]
}
extension Frame {
/// Pack struct to binary
func bytes(version: String) -> [UInt8] {
if version == "5.0" {
let fixedHeader = self.fixedHeader()
let variableHeader5 = self.variableHeader5()
let payload5 = self.payload5()
let properties = self.properties()
let len5 = UInt32(variableHeader5.count + properties.count + payload5.count)
printDebug("==========================MQTT 5.0==========================")
printDebug("packetFixedHeaderType \(packetFixedHeaderType)")
printDebug("fixedHeader \(fixedHeader)")
printDebug("remainingLen(len: len) \(remainingLen(len: len5))")
printDebug("variableHeader \(variableHeader5)")
printDebug("properties \(properties)")
printDebug("payload \(payload5)")
printDebug("=============================================================")
return [packetFixedHeaderType] + remainingLen(len: len5) + variableHeader5 + properties + payload5
} else {
let variableHeader = self.variableHeader()
let payload = self.payload()
let len = UInt32(variableHeader.count + payload.count)
printDebug("=========================MQTT 3.1.1=========================")
printDebug("packetFixedHeaderType \(packetFixedHeaderType)")
printDebug("remainingLen(len: len) \(remainingLen(len: len))")
printDebug("variableHeader \(variableHeader)")
printDebug("payload \(payload)")
printDebug("=============================================================")
return [packetFixedHeaderType] + remainingLen(len: len) + variableHeader + payload
}
}
private func remainingLen(len: UInt32) -> [UInt8] {
var bytes: [UInt8] = []
var digit: UInt8 = 0
var len = len
repeat {
digit = UInt8(len % 128)
len /= 128
// if there are more digits to encode, set the top bit of this digit
if len > 0 {
digit |= 0x80
}
bytes.append(digit)
} while len > 0
return bytes
}
}
/// Fixed Header Attributes
extension Frame {
/// The Fixed Header consist of the following attritutes
///
/// +---------+----------+-------+--------+
/// | 7 6 5 4 | 3 | 2 1 | 0 |
/// +---------+----------+-------+--------+
/// | Type | DUP flag | QoS | RETAIN |
/// +-------------------------------------+
/// The type of the Frame
var type: FrameType {
return FrameType(rawValue: packetFixedHeaderType & 0xF0)!
}
/// Dup flag
var dup: Bool {
get {
return ((packetFixedHeaderType & 0x08) >> 3) == 0 ? false : true
}
set {
packetFixedHeaderType = (packetFixedHeaderType & 0xF7) | (newValue.bit << 3)
}
}
/// Qos level
var qos: CocoaMQTTQoS {
get {
return CocoaMQTTQoS(rawValue: (packetFixedHeaderType & 0x06) >> 1)!
}
set {
packetFixedHeaderType = (packetFixedHeaderType & 0xF9) | (newValue.rawValue << 1)
}
}
/// Retained flag
var retained: Bool {
get {
return (packetFixedHeaderType & 0x01) == 0 ? false : true
}
set {
packetFixedHeaderType = (packetFixedHeaderType & 0xFE) | newValue.bit
}
}
}

87
Pods/CocoaMQTT/Source/FrameAuth.swift generated Normal file
View File

@ -0,0 +1,87 @@
//
// FrameAuth.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/4.
//
import Foundation
struct FrameAuth: Frame {
var packetFixedHeaderType: UInt8 = FrameType.auth.rawValue
// 3.15.2.1 Authenticate Reason Code
var sendReasonCode: CocoaMQTTAUTHReasonCode?
var receiveReasonCode: CocoaMQTTAUTHReasonCode?
// 3.15.2.2 AUTH Properties
var authProperties: MqttAuthProperties?
init(reasonCode: CocoaMQTTAUTHReasonCode, authProperties: MqttAuthProperties) {
self.sendReasonCode = reasonCode
self.authProperties = authProperties
}
}
extension FrameAuth {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.auth.rawValue]
// header += [UInt8(variableHeader5().count)]
return header
}
func variableHeader5() -> [UInt8] {
var header = [UInt8]()
header += [sendReasonCode!.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return []}
func properties() -> [UInt8] {
return authProperties?.properties ?? []
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return [] }
func payload() -> [UInt8] { return [] }
}
extension FrameAuth: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
guard protocolVersion == "5.0" else {
return nil
}
if bytes.isEmpty {
receiveReasonCode = .success
} else {
receiveReasonCode = CocoaMQTTAUTHReasonCode(rawValue: bytes[0])
}
}
}

110
Pods/CocoaMQTT/Source/FrameConnAck.swift generated Normal file
View File

@ -0,0 +1,110 @@
//
// FrameConnack.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
struct FrameConnAck: Frame {
var packetFixedHeaderType: UInt8 = FrameType.connack.rawValue
// --- Attributes
/// MQTT 3.1.1
var returnCode: CocoaMQTTConnAck?
/// MQTT 5.0
var reasonCode: CocoaMQTTCONNACKReasonCode?
// 3.2.2.1.1 Session Present
var sessPresent: Bool = false
// --- Attributes End
// 3.2.2.3 CONNACK Properties
var connackProperties: MqttDecodeConnAck?
var propertiesBytes: [UInt8]?
// 3.2.3 CONNACK Payload
// The CONNACK packet has no Payload.
/// MQTT 3.1.1
init(returnCode: CocoaMQTTConnAck) {
self.returnCode = returnCode
}
/// MQTT 5.0
init(code: CocoaMQTTCONNACKReasonCode) {
reasonCode = code
}
}
extension FrameConnAck {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.connack.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
return [sessPresent.bit, reasonCode!.rawValue]
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] { return propertiesBytes ?? [] }
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] {
return [sessPresent.bit, returnCode!.rawValue]
}
func payload() -> [UInt8] { return [] }
}
extension FrameConnAck: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.connack.rawValue else {
return nil
}
guard bytes.count >= 2 else {
return nil
}
sessPresent = Bool(bit: bytes[0] & 0x01)
let mqtt5ack = CocoaMQTTCONNACKReasonCode(rawValue: bytes[1])
reasonCode = mqtt5ack
let ack = CocoaMQTTConnAck(byte: bytes[1])
returnCode = ack
propertiesBytes = bytes
self.connackProperties = MqttDecodeConnAck()
self.connackProperties!.properties(connackData: bytes)
}
}
extension FrameConnAck: CustomStringConvertible {
var description: String {
return "CONNACK(code: \(String(describing: reasonCode)), sp: \(sessPresent))"
}
}

288
Pods/CocoaMQTT/Source/FrameConnect.swift generated Normal file
View File

@ -0,0 +1,288 @@
//
// ConnectFrame.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT CONNECT Frame
struct FrameConnect: Frame {
var packetFixedHeaderType: UInt8 = FrameType.connect.rawValue
/// MQTT 3.1.1
private let PROTOCOL_LEVEL = UInt8(4)
private let PROTOCOL_VERSION: String = "MQTT/3.1.1"
private let PROTOCOL_MAGIC: String = "MQTT"
// --- Attributes
// 3.1.2.1
let protocolName: String = "MQTT"
// 3.1.2.2 Protocol Version
let protocolVersion = UInt8(5)
// 3.1.2.5 Will Flag
var willMsg: CocoaMQTTMessage?
var willMsg5: CocoaMQTT5Message?
// 3.1.2.6 Will QoS
var willQoS: UInt8?
// 3.1.2.7 Will Retain
var willRetain: Bool = true
// 3.1.2.8 User Name Flag
var username: String?
// 3.1.2.9 Password Flag
var password: String?
// 3.1.2.10 Keep Alive
var keepAlive: UInt16 = 10
var cleansess: Bool = true
// 3.1.2
// 3.1.2.11 CONNECT Properties
var connectProperties: MqttConnectProperties?
var authenticationData: Data?
// 3.1.3.1 Client Identifier (ClientID)
var clientID: String
// --- Attributes End
init(clientID: String) {
self.clientID = clientID
}
}
extension FrameConnect {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.connect.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
var header = [UInt8]()
var flags = ConnFlags()
// 3.1.2.1 Protocol Name
header += protocolName.bytesWithLength
// 3.1.2.2 Protocol Version
header.append(protocolVersion)
// 3.1.2.3 Connect Flags
if let will = willMsg5 {
flags.flagWill = true
flags.flagWillQoS = will.qos.rawValue
flags.flagWillRetain = will.retained
}
if username != nil {
flags.flagUsername = true
// Append password attribute if username presented
if password != nil {
flags.flagPassword = true
}
}
flags.flagCleanSession = cleansess
header.append(flags.rawValue)
header += keepAlive.hlBytes
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func properties() -> [UInt8] {
return connectProperties?.properties ?? []
}
func payload5() -> [UInt8] {
var payload = [UInt8]()
payload += clientID.bytesWithLength
if let will = willMsg5 {
payload += beVariableByteInteger(length: willMsg5!.properties.count)
payload += will.properties
payload += will.topic.bytesWithLength
payload += UInt16(will.payload.count).hlBytes
payload += will.payload
}
if let username = username {
payload += username.bytesWithLength
// Append password attribute if username presented
if let password = password {
payload += password.bytesWithLength
}
}
return payload
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] {
var header = [UInt8]()
var flags = ConnFlags()
// variable header
header += PROTOCOL_MAGIC.bytesWithLength
header.append(PROTOCOL_LEVEL)
if let will = willMsg {
flags.flagWill = true
flags.flagWillQoS = will.qos.rawValue
flags.flagWillRetain = will.retained
}
if username != nil {
flags.flagUsername = true
// Append password attribute if username presented
if password != nil {
flags.flagPassword = true
}
}
flags.flagCleanSession = cleansess
header.append(flags.rawValue)
header += keepAlive.hlBytes
return header
}
func payload() -> [UInt8] {
var payload = [UInt8]()
payload += clientID.bytesWithLength
if let will = willMsg {
payload += will.topic.bytesWithLength
payload += UInt16(will.payload.count).hlBytes
payload += will.payload
}
if let username = username {
payload += username.bytesWithLength
// Append password attribute if username presented
if let password = password {
payload += password.bytesWithLength
}
}
return payload
}
}
extension FrameConnect: CustomStringConvertible {
var description: String {
return "CONNECT(id: \(clientID), username: \(username ?? "nil"), " +
"password: \(password ?? "nil"), keepAlive : \(keepAlive), " +
"cleansess: \(cleansess))"
}
}
/// Connect Flags
private struct ConnFlags {
/// These Flags consist of following flags:
///
/// +----------+----------+------------+--------------------+--------------+----------+
/// | 7 | 6 | 5 | 4 3 | 2 | 1 | 0 |
/// +----------+----------+------------+---------+----------+--------------+----------+
/// | username | password | willretain | willqos | willflag | cleansession | reserved |
/// +----------+----------+------------+---------+----------+--------------+----------+
///
var rawValue: UInt8 = 0
var flagUsername: Bool {
get {
return Bool(bit: (rawValue >> 7) & 0x01)
}
set {
rawValue = (rawValue & 0x7F) | (newValue.bit << 7)
}
}
var flagPassword: Bool {
get {
return Bool(bit: (rawValue >> 6) & 0x01)
}
set {
rawValue = (rawValue & 0xBF) | (newValue.bit << 6)
}
}
var flagWillRetain: Bool {
get {
return Bool(bit: (rawValue >> 5) & 0x01)
}
set {
rawValue = (rawValue & 0xDF) | (newValue.bit << 5)
}
}
var flagWillQoS: UInt8 {
get {
return (rawValue >> 3) & 0x03
}
set {
rawValue = (rawValue & 0xE7) | (newValue << 3)
}
}
var flagWill: Bool {
get {
return Bool(bit: (rawValue >> 2) & 0x01)
}
set {
rawValue = (rawValue & 0xFB) | (newValue.bit << 2)
}
}
var flagCleanSession: Bool {
get {
return Bool(bit: (rawValue >> 1) & 0x01)
}
set {
rawValue = (rawValue & 0xFD) | (newValue.bit << 1)
}
}
}

View File

@ -0,0 +1,128 @@
//
// FrameDisconnect.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT Disconnect packet
struct FrameDisconnect: Frame {
var packetFixedHeaderType: UInt8 = FrameType.disconnect.rawValue
// 3.14.2 DISCONNECT Variable Header
public var sendReasonCode: CocoaMQTTDISCONNECTReasonCode?
public var receiveReasonCode: CocoaMQTTDISCONNECTReasonCode?
// 3.14.2.2.2 Session Expiry Interval
public var sessionExpiryInterval: UInt32?
// 3.14.2.2.3 Reason String
public var reasonString: String?
// 3.14.2.2.4 User Property
public var userProperties: [String: String]?
// 3.14.2.2.5 Server Reference
public var serverReference: String?
/// MQTT 3.1.1
init() { /* Nothing to do */ }
/// MQTT 5.0
init(disconnectReasonCode: CocoaMQTTDISCONNECTReasonCode) {
self.sendReasonCode = disconnectReasonCode
}
}
extension FrameDisconnect {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.disconnect.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
var header = [UInt8]()
header += [sendReasonCode!.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.14.2.2.2 Session Expiry Interval
if let sessionExpiryInterval = self.sessionExpiryInterval {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.sessionExpiryInterval.rawValue, value: sessionExpiryInterval.byteArrayLittleEndian)
}
// 3.14.2.2.3 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.14.2.2.4 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
// 3.14.2.2.5 Server Reference
if let serverReference = self.serverReference {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.serverReference.rawValue, value: serverReference.bytesWithLength)
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return [] }
func payload() -> [UInt8] { return [] }
}
extension FrameDisconnect: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
if bytes.isEmpty {
receiveReasonCode = .normalDisconnection
} else {
receiveReasonCode = CocoaMQTTDISCONNECTReasonCode(rawValue: bytes[0])
}
} else {
return nil
}
}
}
extension FrameDisconnect: CustomStringConvertible {
var description: String {
return "DISCONNECT"
}
}

54
Pods/CocoaMQTT/Source/FramePingReq.swift generated Normal file
View File

@ -0,0 +1,54 @@
//
// FramePingReq.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
struct FramePingReq: Frame {
var packetFixedHeaderType: UInt8 = FrameType.pingreq.rawValue
}
extension FramePingReq {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.pingreq.rawValue]
return header
}
func variableHeader5() -> [UInt8] { return [] }
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] { return [] }
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return [] }
func payload() -> [UInt8] { return [] }
}
extension FramePingReq: CustomStringConvertible {
var description: String {
return "PING"
}
}

View File

@ -0,0 +1,68 @@
//
// FramePingResp.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT PINGRESP packet
struct FramePingResp: Frame {
var packetFixedHeaderType: UInt8 = FrameType.pingresp.rawValue
}
extension FramePingResp {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.pingresp.rawValue]
return header
}
func variableHeader5() -> [UInt8] { return [] }
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] { return [] }
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return [] }
func payload() -> [UInt8] { return [] }
}
extension FramePingResp: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.pingresp.rawValue else {
return nil
}
guard bytes.count == 0 else {
return nil
}
}
}
extension FramePingResp: CustomStringConvertible {
var description: String {
return "PONG"
}
}

129
Pods/CocoaMQTT/Source/FramePubAck.swift generated Normal file
View File

@ -0,0 +1,129 @@
//
// FramePuback.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT PUBACK packet
struct FramePubAck: Frame {
var packetFixedHeaderType: UInt8 = FrameType.puback.rawValue
// --- Attributes
var msgid: UInt16
// --- Attributes End
// 3.4.2.1 PUBACK Reason Code
public var reasonCode: CocoaMQTTPUBACKReasonCode?
// 3.4.2.2 PUBACK Properties
public var pubAckProperties: MqttDecodePubAck?
// 3.4.2.2.2 Reason String
public var reasonString: String?
// 3.4.2.2.3 User Property
public var userProperties: [String: String]?
/// MQTT 3.1.1
init(msgid: UInt16) {
self.msgid = msgid
}
/// MQTT 5.0
init(msgid: UInt16, reasonCode: CocoaMQTTPUBACKReasonCode) {
self.msgid = msgid
self.reasonCode = reasonCode
}
}
extension FramePubAck {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.puback.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.4.2 MSB+LSB
var header = msgid.hlBytes
// 3.4.2.1 PUBACK Reason Code
header += [reasonCode!.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.4.2.2.2 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.4.2.2.3 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] { return [] }
}
extension FramePubAck: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.puback.rawValue else {
return nil
}
// MQTT 5.0 bytes.count == 4
guard bytes.count >= 2 else {
return nil
}
if bytes.count > 2 {
self.reasonCode = CocoaMQTTPUBACKReasonCode(rawValue: bytes[2])
self.pubAckProperties = MqttDecodePubAck()
self.pubAckProperties!.decodePubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
}
msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
}
}
extension FramePubAck: CustomStringConvertible {
var description: String {
return "PUBACK(id: \(msgid))"
}
}

127
Pods/CocoaMQTT/Source/FramePubComp.swift generated Normal file
View File

@ -0,0 +1,127 @@
//
// FramePubCom.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// ublish complete (QoS 2 delivery part 3)
/// The PUBCOMP packet is the response to a PUBREL packet. It is the fourth and final packet of the QoS 2 protocol exchange.
struct FramePubComp: Frame {
var packetFixedHeaderType: UInt8 = FrameType.pubcomp.rawValue
// --- Attributes
var msgid: UInt16
// --- Attributes End
// 3.7.2.1 PUBCOMP Reason Code
public var reasonCode: CocoaMQTTPUBCOMPReasonCode?
// 3.7.2.2 PUBCOMP Properties
public var pubCompProperties: MqttDecodePubComp?
// 3.7.2.2.2 Reason String
public var reasonString: String?
// 3.7.2.2.3 User Property
public var userProperties: [String: String]?
/// MQTT 3.1.1
init(msgid: UInt16) {
self.msgid = msgid
}
/// MQTT 5.0
init(msgid: UInt16, reasonCode: CocoaMQTTPUBCOMPReasonCode) {
self.msgid = msgid
self.reasonCode = reasonCode
}
}
extension FramePubComp {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.pubcomp.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.7.2 MSB+LSB
var header = msgid.hlBytes
// 3.7.2.1 PUBACK Reason Code
header += [reasonCode!.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.7.2.2.2 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.7.2.2.3 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] { return [] }
}
extension FramePubComp: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.pubcomp.rawValue else {
return nil
}
guard bytes.count >= 2 else {
return nil
}
msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.pubCompProperties = MqttDecodePubComp()
self.pubCompProperties!.decodePubComp(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
}
}
extension FramePubComp: CustomStringConvertible {
var description: String {
return "PUBCOMP(id: \(msgid))"
}
}

125
Pods/CocoaMQTT/Source/FramePubRec.swift generated Normal file
View File

@ -0,0 +1,125 @@
//
// FramePubRec.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT PUBREC packet
struct FramePubRec: Frame {
var packetFixedHeaderType: UInt8 = FrameType.pubrec.rawValue
// --- Attributes
var msgid: UInt16
// --- Attributes End
// 3.5.2.1 PUBREC Reason Code
public var reasonCode: CocoaMQTTPUBRECReasonCode?
// 3.5.2.2 PUBREC Properties
public var pubRecProperties: MqttDecodePubRec?
// 3.5.2.2.2 Reason String
public var reasonString: String?
// 3.5.2.2.3 User Property
public var userProperties: [String: String]?
/// MQTT 3.1.1
init(msgid: UInt16) {
self.msgid = msgid
}
/// MQTT 5.0
init(msgid: UInt16, reasonCode: CocoaMQTTPUBRECReasonCode) {
self.msgid = msgid
self.reasonCode = reasonCode
}
}
extension FramePubRec {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.pubrec.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.5.2 MSB+LSB
var header = msgid.hlBytes
// 3.5.2.1 PUBACK Reason Code
header += [reasonCode!.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.5.2.2.2 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.5.2.2.3 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] { return [] }
}
extension FramePubRec: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.pubrec.rawValue else {
return nil
}
guard bytes.count >= 2 else {
return nil
}
msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.pubRecProperties = MqttDecodePubRec()
self.pubRecProperties!.decodePubRec(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
}
}
extension FramePubRec: CustomStringConvertible {
var description: String {
return "PUBREC(id: \(msgid))"
}
}

120
Pods/CocoaMQTT/Source/FramePubRel.swift generated Normal file
View File

@ -0,0 +1,120 @@
//
// FramePubRel.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT PUBREL packet
/// A PUBREL packet is the response to a PUBREC packet. It is the third packet of the QoS 2 protocol exchange.
struct FramePubRel: Frame {
var packetFixedHeaderType: UInt8 = UInt8(FrameType.pubrel.rawValue + 2)
// --- Attributes
var msgid: UInt16
// --- Attributes End
// 3.6.2.1 PUBREL Reason Code
public var reasonCode: CocoaMQTTPUBRELReasonCode = .success
// 3.6.2.2 PUBREL Properties
public var pubRelProperties: MqttDecodePubRel?
// 3.6.2.2.2 Reason String
public var reasonString: String?
// 3.6.2.2.3 User Property
public var userProperties: [String: String]?
init(msgid: UInt16) {
self.msgid = msgid
qos = .qos1
}
}
extension FramePubRel {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.pubrel.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.6.2 MSB+LSB
var header = msgid.hlBytes
// 3.6.2.1 PUBACK Reason Code
header += [reasonCode.rawValue]
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return [] }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.6.2.2.2 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.6.2.2.3 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] { return [] }
}
extension FramePubRel: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == 0x62 else {
return nil
}
guard bytes.count >= 2 else {
return nil
}
self.packetFixedHeaderType = packetFixedHeaderType
msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.pubRelProperties = MqttDecodePubRel()
self.pubRelProperties!.decodePubRel(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
}
}
extension FramePubRel: CustomStringConvertible {
var description: String {
return "PUBREL(id: \(msgid))"
}
}

237
Pods/CocoaMQTT/Source/FramePublish.swift generated Normal file
View File

@ -0,0 +1,237 @@
//
// FramePublish.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
// MQTT PUBLISH Frame
struct FramePublish: Frame {
// 3.3.1.4 Remaining Length
public var remainingLength: UInt32?
// 3.3.2.1 Topic Name
public var topicName: String?
// 3.3.2.2 Packet Identifier
public var packetIdentifier: UInt16?
// 3.3.2.3 PUBLISH Properties
public var publishProperties: MqttPublishProperties?
public var publishRecProperties: MqttDecodePublish?
var packetFixedHeaderType: UInt8 = FrameType.publish.rawValue
// --- Attributes
var msgid: UInt16
var topic: String = ""
var _payload: [UInt8] = []
var mqtt5Topic: String = ""
// --- Attributes End
init(topic: String, payload: [UInt8], qos: CocoaMQTTQoS = .qos0, msgid: UInt16 = 0) {
self.topic = topic
self._payload = payload
self.msgid = msgid
self.qos = qos
}
}
extension FramePublish {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.publish.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.3.2.1 Topic Name
var header = self.topic.bytesWithLength
// 3.3.2.2 Packet Identifier qos1 or qos2
if qos > .qos0 {
header += msgid.hlBytes
// header.append(UInt8(0))
// header.append(QoS.rawValue)
}
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return _payload }
func properties() -> [UInt8] {
// Properties
return publishProperties?.properties ?? []
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] {
var header = topic.bytesWithLength
if qos > .qos0 {
header += msgid.hlBytes
}
return header
}
func payload() -> [UInt8] { return _payload }
}
extension FramePublish: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType & 0xF0 == FrameType.publish.rawValue else {
return nil
}
let recDup = ((packetFixedHeaderType & 0b0000_1000) >> 3) > 0
guard let recQos = CocoaMQTTQoS(rawValue: (packetFixedHeaderType & 0b0000_0110) >> 1) else {
return nil
}
let recRetain = (packetFixedHeaderType & 0b0000_0001) > 0
// Reserved
var flags: UInt8 = 0
if recRetain {
flags = flags | 0b0000_0001
} else {
flags = flags | 0b0000_0000
}
if recDup {
flags = flags | 0b0011_1000
} else {
flags = flags | 0b0011_0000
}
switch recQos {
case .qos0:
flags = flags | 0b0011_0000
case .qos1:
flags = flags | 0b0011_0010
case .qos2:
flags = flags | 0b0011_0100
case .FAILURE:
printDebug("FAILTURE")
}
self.packetFixedHeaderType = flags
// Packet Identifier
// The Packet Identifier field is only present in PUBLISH packets where the QoS level is 1 or 2.
// parse topic
if bytes.count < 2 {
return nil
}
let topicLength = Int(UInt16(bytes[0]) << 8 | UInt16(bytes[1]))
let topicStart = 2
let topicEnd = topicStart + topicLength
if bytes.count < topicEnd {
return nil
}
var pos = topicEnd
// msgid
if (packetFixedHeaderType & 0x06) >> 1 == CocoaMQTTQoS.qos0.rawValue {
msgid = 0
} else {
if bytes.count < pos + 2 {
return nil
}
msgid = UInt16(bytes[pos]) << 8 + UInt16(bytes[pos+1])
pos += 2
}
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
let data = MqttDecodePublish()
data.decodePublish(fixedHeader: packetFixedHeaderType, publishData: bytes)
pos = data.mqtt5DataIndex
if data.propertyLength != 0 {
pos += data.propertyLength!
}
if pos > bytes.count {
return nil
}
// MQTT 5.0: Topic Name may be empty only when Topic Alias is present.
if data.topic.isEmpty && data.topicAlias == nil {
return nil
}
// MQTT 5.0
self.mqtt5Topic = data.topic
self.topic = data.topic
self.packetIdentifier = data.packetIdentifier
if let packetIdentifier = data.packetIdentifier {
self.msgid = packetIdentifier
}
self.publishRecProperties = data
} else {
// MQTT 3.1.1
guard topicLength > 0 else {
return nil
}
guard let recTopic = String(bytes: bytes[topicStart..<topicEnd], encoding: .utf8) else {
return nil
}
topic = recTopic
}
// payload
if pos == bytes.count {
_payload = []
} else if pos < bytes.count {
_payload = [UInt8](bytes[pos..<bytes.count])
} else {
return nil
}
}
}
extension FramePublish: CustomStringConvertible {
var description: String {
return "PUBLISH(id: \(msgid), topic: \(topic), payload: \(_payload.summary))"
}
}

163
Pods/CocoaMQTT/Source/FrameSubAck.swift generated Normal file
View File

@ -0,0 +1,163 @@
//
// FrameSubAck.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT SUBACK packet
struct FrameSubAck: Frame {
var packetFixedHeaderType: UInt8 = FrameType.suback.rawValue
// --- Attributes
var msgid: UInt16
var grantedQos: [CocoaMQTTQoS]
// --- Attributes End
// 3.9.2.1.2 Reason String
public var reasonString: String?
// 3.9.2.1.3 User Property
public var userProperties: [String: String]?
// 3.9.3 The order of Reason Codes in the SUBACK packet MUST match the order of Topic Filters in the SUBSCRIBE packet [MQTT-3.9.3-1].
public var reasonCodes: [CocoaMQTTSUBACKReasonCode]?
// 3.9.2.1 SUBACK Properties
public var subAckProperties: MqttDecodeSubAck?
init(msgid: UInt16, grantedQos: [CocoaMQTTQoS]) {
self.msgid = msgid
self.grantedQos = grantedQos
}
}
extension FrameSubAck {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.suback.rawValue]
return header
}
func variableHeader5() -> [UInt8] { return msgid.hlBytes }
func payload5() -> [UInt8] {
var payload = [UInt8]()
for qos in grantedQos {
payload.append(qos.rawValue)
}
return payload
}
func properties() -> [UInt8] { return [] }
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] {
var payload = [UInt8]()
for qos in grantedQos {
payload.append(qos.rawValue)
}
return payload
}
}
extension FrameSubAck: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
self.packetFixedHeaderType = packetFixedHeaderType
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// the bytes length must bigger than 3
guard bytes.count >= 4 else {
return nil
}
self.msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.grantedQos = []
self.reasonCodes = [CocoaMQTTSUBACKReasonCode]()
let propertyLength = decodeVariableByteInteger(data: bytes, offset: 2)
let reasonCodesStartIndex = propertyLength.newOffset + propertyLength.res
guard reasonCodesStartIndex < bytes.count else {
return nil
}
for i in reasonCodesStartIndex ..< bytes.count {
guard let reasonCode = CocoaMQTTSUBACKReasonCode(rawValue: bytes[i]) else {
return nil
}
self.reasonCodes! += [reasonCode]
switch reasonCode {
case .grantedQoS0:
self.grantedQos.append(.qos0)
case .grantedQoS1:
self.grantedQos.append(.qos1)
case .grantedQoS2:
self.grantedQos.append(.qos2)
default:
self.grantedQos.append(.FAILURE)
}
}
self.subAckProperties = MqttDecodeSubAck()
self.subAckProperties!.decodeSubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
} else {
// the bytes length must bigger than 3
guard bytes.count >= 3 else {
return nil
}
self.msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.grantedQos = []
for i in 2 ..< bytes.count {
guard let qos = CocoaMQTTQoS(rawValue: bytes[i]) else {
return nil
}
self.grantedQos.append(qos)
}
}
}
}
extension FrameSubAck: CustomStringConvertible {
var description: String {
return "SUBACK(id: \(msgid))"
}
}

174
Pods/CocoaMQTT/Source/FrameSubscribe.swift generated Normal file
View File

@ -0,0 +1,174 @@
//
// FrameSubscribe.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT SUBSCRIBE Frame
struct FrameSubscribe: Frame {
var packetFixedHeaderType: UInt8 = UInt8(FrameType.subscribe.rawValue + 2)
// --- Attributes
var msgid: UInt16?
var topics: [(String, CocoaMQTTQoS)]?
// --- Attributes End
// 3.8.2 SUBSCRIBE Variable Header
public var packetIdentifier: UInt16?
// 3.8.2.1.2 Subscription Identifier
public var subscriptionIdentifier: UInt32?
// 3.8.2.1.3 User Property
public var userProperty: [String: String]?
// 3.8.3 SUBSCRIBE Payload
public var topicFilters: [MqttSubscription]?
/// MQTT 3.1.1
init(msgid: UInt16, topic: String, reqos: CocoaMQTTQoS) {
self.init(msgid: msgid, topics: [(topic, reqos)])
}
init(msgid: UInt16, topics: [(String, CocoaMQTTQoS)]) {
packetFixedHeaderType = FrameType.subscribe.rawValue
self.msgid = msgid
self.topics = topics
qos = CocoaMQTTQoS.qos1
}
/// MQTT 5.0
init(msgid: UInt16, subscriptionList: [MqttSubscription]) {
self.msgid = msgid
self.topicFilters = subscriptionList
}
/// MQTT 5.0
init(msgid: UInt16, subscriptionList: [MqttSubscription], packetIdentifier: UInt16? = nil, subscriptionIdentifier: UInt32? = nil, userProperty: [String: String] = [:]) {
self.msgid = msgid
self.topicFilters = subscriptionList
if packetIdentifier != nil {
self.packetIdentifier = packetIdentifier
}
if subscriptionIdentifier != nil {
self.subscriptionIdentifier = subscriptionIdentifier
}
if !userProperty.isEmpty {
self.userProperty = userProperty
}
}
}
extension FrameSubscribe {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.subscribe.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.8.2 SUBSCRIBE Variable Header
// The Variable Header of the SUBSCRIBE Packet contains the following fields in the order: Packet Identifier, and Properties.
// MQTT 5.0
var header = [UInt8]()
header = msgid!.hlBytes
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] {
var payload = [UInt8]()
for subscription in self.topicFilters! {
subscription.subscriptionOptions = true
payload += subscription.subscriptionData
}
return payload
}
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.8.2.1.2 Subscription Identifier
if let subscriptionIdentifier = self.subscriptionIdentifier,
let subscriptionIdentifier = beVariableByteInteger(subscriptionIdentifier) {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.subscriptionIdentifier.rawValue, value: subscriptionIdentifier)
}
// 3.8.2.1.3 User Property
if let userProperty = self.userProperty {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid!.hlBytes }
func payload() -> [UInt8] {
var payload = [UInt8]()
for (topic, qos) in topics! {
payload += topic.bytesWithLength
payload.append(qos.rawValue)
}
return payload
}
}
extension FrameSubscribe: CustomStringConvertible {
var description: String {
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
var desc = ""
if let unwrappedList = topicFilters, !unwrappedList.isEmpty {
for subscription in unwrappedList {
desc += "SUBSCRIBE(id: \(String(describing: msgid)), topics: \(subscription.topic)) "
}
}
return desc
} else {
return "SUBSCRIBE(id: \(String(describing: msgid)), topics: \(String(describing: topics)))"
}
}
}

117
Pods/CocoaMQTT/Source/FrameUnsubAck.swift generated Normal file
View File

@ -0,0 +1,117 @@
//
// FrameUnsubAck.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT UNSUBACK packet
struct FrameUnsubAck: Frame {
var packetFixedHeaderType: UInt8 = FrameType.unsuback.rawValue
// --- Attributes
var msgid: UInt16
// --- Attributes End
// 3.10.2.1 UNSUBSCRIBE Properties
public var unSubAckProperties: MqttDecodeUnsubAck?
// 3.11.2 Property
public var userProperty: [String: String]?
// 3.11.2.1.2 Reason String
public var reasonString: String?
var _payload: [UInt8] = []
init(msgid: UInt16, payload: [UInt8]) {
self.msgid = msgid
self._payload = payload
}
}
extension FrameUnsubAck {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.unsuback.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// 3.11.2 MSB+LSB
var header = msgid.hlBytes
// MQTT 5.0
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] { return _payload }
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.11.2.1.2 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.11.2.1.3 User Property
if let userProperty = self.userProperty {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid.hlBytes }
func payload() -> [UInt8] { return [] }
}
extension FrameUnsubAck: InitialWithBytes {
init?(packetFixedHeaderType: UInt8, bytes: [UInt8]) {
guard packetFixedHeaderType == FrameType.unsuback.rawValue else {
return nil
}
guard bytes.count >= 2 else {
return nil
}
msgid = UInt16(bytes[0]) << 8 + UInt16(bytes[1])
self.unSubAckProperties = MqttDecodeUnsubAck()
self.unSubAckProperties!.decodeUnSubAck(fixedHeader: packetFixedHeaderType, pubAckData: bytes)
}
}
extension FrameUnsubAck: CustomStringConvertible {
var description: String {
return "UNSUBSACK(id: \(msgid))"
}
}

View File

@ -0,0 +1,139 @@
//
// FrameUnsubscribe.swift
// CocoaMQTT
//
// Created by JianBo on 2019/8/7.
// Copyright © 2019 emqx.io. All rights reserved.
//
import Foundation
/// MQTT UNSUBSCRIBE packet
struct FrameUnsubscribe: Frame {
var packetFixedHeaderType: UInt8 = UInt8(FrameType.unsubscribe.rawValue + 2)
// --- Attributes
var msgid: UInt16?
/// MQTT 3.1.1
var topics: [String]?
/// MQTT 5.0
var topicFilters: [MqttSubscription]?
// --- Attribetes end
// 3.10.2.1.2 User Property
public var userProperty: [String: String]?
/// MQTT 3.1.1
init(msgid: UInt16, topics: [String]) {
self.msgid = msgid
self.topics = topics
qos = CocoaMQTTQoS.qos1
}
/// MQTT 5.0
init(msgid: UInt16, topics: [MqttSubscription]) {
self.msgid = msgid
self.topicFilters = topics
qos = CocoaMQTTQoS.qos1
}
}
extension FrameUnsubscribe {
func fixedHeader() -> [UInt8] {
var header = [UInt8]()
header += [FrameType.unsubscribe.rawValue]
return header
}
func variableHeader5() -> [UInt8] {
// MQTT 5.0
var header = [UInt8]()
header = msgid!.hlBytes
header += beVariableByteInteger(length: self.properties().count)
return header
}
func payload5() -> [UInt8] {
var payload = [UInt8]()
for subscription in topicFilters! {
subscription.subscriptionOptions = false
payload += subscription.subscriptionData
}
return payload
}
func properties() -> [UInt8] {
var properties = [UInt8]()
// 3.10.2.1.2 User Property
if let userProperty = self.userProperty {
properties += userProperty.userPropertyBytes
}
return properties
}
func allData() -> [UInt8] {
var allData = [UInt8]()
allData += fixedHeader()
allData += variableHeader5()
allData += properties()
allData += payload5()
return allData
}
func variableHeader() -> [UInt8] { return msgid!.hlBytes }
func payload() -> [UInt8] {
var payload = [UInt8]()
for t in topics! {
payload += t.bytesWithLength
}
return payload
}
}
extension FrameUnsubscribe: CustomStringConvertible {
var description: String {
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
var desc = ""
if let unwrappedList = topicFilters, !unwrappedList.isEmpty {
for subscription in unwrappedList {
desc += "UNSUBSCRIBE(id: \(String(describing: subscription.topic)), topics: \(subscription.topic)) "
}
}
return desc
} else {
return "UNSUBSCRIBE(id: \(String(describing: msgid)), topics: \(String(describing: topics)))"
}
}
}

View File

@ -0,0 +1,44 @@
//
// MqttAuthProperties.swift
// CocoaMQTT
//
// Created by liwei wang on 1/9/2021.
//
import Foundation
public class MqttAuthProperties: NSObject {
// 3.15.2.2.2 Authentication Method
public var authenticationMethod: String?
// 3.15.2.2.3 Authentication Data
public var authenticationData: [UInt8]?
// 3.15.2.2.4 Reason String
public var reasonString: String?
// 3.15.2.2.5 User Property
public var userProperties: [String: String]?
public var properties: [UInt8] {
var properties = [UInt8]()
// 3.15.2.2.2 Authentication Method
if let authenticationMethod = self.authenticationMethod {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.authenticationMethod.rawValue, value: authenticationMethod.bytesWithLength)
}
// 3.15.2.2.3 Authentication Data
if let authenticationData = self.authenticationData {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.authenticationData.rawValue, value: authenticationData)
}
// 3.15.2.2.4 Reason String
if let reasonString = self.reasonString {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.reasonString.rawValue, value: reasonString.bytesWithLength)
}
// 3.15.2.2.5 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
return properties
}
}

View File

@ -0,0 +1,80 @@
//
// MqttConnectProperties.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/25.
//
import Foundation
public class MqttConnectProperties: NSObject {
// 3.1.2.11.1 Property Length
// public var propertyLength: UInt8?
// 3.1.2.11.2 Session Expiry Interval
public var sessionExpiryInterval: UInt32?
// 3.1.2.11.3 Receive Maximum
public var receiveMaximum: UInt16?
// 3.1.2.11.4 Maximum Packet Size
public var maximumPacketSize: UInt32?
// 3.1.2.11.5 Topic Alias Maximum
public var topicAliasMaximum: UInt16?
// 3.1.2.11.6 Request Response Information
public var requestResponseInformation: UInt8?
// 3.1.2.11.7 Request Problem Information
public var requestProblemInfomation: UInt8?
// 3.1.2.11.8 User Property
public var userProperties: [String: String]?
// 3.1.2.11.9 Authentication Method
public var authenticationMethod: String?
// 3.1.2.11.10 Authentication Data
public var authenticationData: [UInt8]?
public var properties: [UInt8] {
var properties = [UInt8]()
// 3.1.2.11.2 Session Expiry Interval
if let sessionExpiryInterval = self.sessionExpiryInterval {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.sessionExpiryInterval.rawValue, value: sessionExpiryInterval.byteArrayLittleEndian)
}
// 3.1.2.11.3 Receive Maximum
if let receiveMaximum = self.receiveMaximum {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.receiveMaximum.rawValue, value: receiveMaximum.hlBytes)
}
// 3.1.2.11.4 Maximum Packet Size
if let maximumPacketSize = self.maximumPacketSize {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.maximumPacketSize.rawValue, value: maximumPacketSize.byteArrayLittleEndian)
}
// 3.1.2.11.5 Topic Alias Maximum
if let topicAliasMaximum = self.topicAliasMaximum {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.topicAliasMaximum.rawValue, value: topicAliasMaximum.hlBytes)
}
// 3.1.2.11.6 Request Response Information
if let requestResponseInformation = self.requestResponseInformation {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.requestResponseInformation.rawValue, value: [requestResponseInformation])
}
// 3.1.2.11.7 Request Problem Information
if let requestProblemInfomation = self.requestProblemInfomation {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.requestProblemInformation.rawValue, value: [requestProblemInfomation])
}
// 3.1.2.11.8 User Property
if let userProperty = self.userProperties {
properties += userProperty.userPropertyBytes
}
// 3.1.2.11.9 Authentication Method
if let authenticationMethod = self.authenticationMethod {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.authenticationMethod.rawValue, value: authenticationMethod.bytesWithLength)
}
// 3.1.2.11.10 Authentication Data
if let authenticationData = self.authenticationData {
properties += authenticationData
}
return properties
}
}

View File

@ -0,0 +1,237 @@
//
// MqttDecodeConnAck.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/26.
//
import Foundation
public class MqttDecodeConnAck: NSObject {
// var connackData: [UInt8]
//
// init(connackData: [UInt8]) {
// connackData = connackData
// }
// 3.2.2.3 CONNACK Properties
// 3.2.2.3.1 Property Length
public var propertyLength: Int?
// 3.2.2.3.2 Session Expiry Interval
public var sessionExpiryInterval: UInt32?
// 3.2.2.3.3 Receive Maximum
public var receiveMaximum: UInt16?
// 3.2.2.3.4 Maximum QoS
public var maximumQoS: CocoaMQTTQoS?
// 3.2.2.3.5 Retain Available
public var retainAvailable: Bool?
// 3.2.2.3.6 Maximum Packet Size
public var maximumPacketSize: UInt32?
// 3.2.2.3.7 Assigned Client Identifier
public var assignedClientIdentifier: String?
// 3.2.2.3.8 Topic Alias Maximum
public var topicAliasMaximum: UInt16?
// 3.2.2.3.9 Reason String
public var reasonString: String?
// 3.2.2.3.10 User Property
public var userProperty: [String: String]?
// 3.2.2.3.11 Wildcard Subscription Available
public var wildcardSubscriptionAvailable: Bool?
// 3.2.2.3.12 Subscription Identifiers Available
public var subscriptionIdentifiersAvailable: Bool?
// 3.2.2.3.13 Shared Subscription Available
public var sharedSubscriptionAvailable: Bool?
// 3.2.2.3.14 Server Keep Alive
public var serverKeepAlive: UInt16?
// 3.2.2.3.15 Response Information
public var responseInformation: String?
// 3.2.2.3.16 Server Reference
public var serverReference: String?
// 3.2.2.3.17 Authentication Method
public var authenticationMethod: String?
// 3.2.2.3.18 Authentication Data
public var authenticationData = [UInt8]()
public func properties(connackData: [UInt8]) {
// 3.2.2.3 CONNACK Properties
var index = 2 // sessPresent 0 reasonCode 1
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: connackData, offset: index)
propertyLength = propertyLengthVariableByteInteger.res
index = propertyLengthVariableByteInteger.newOffset
let occupyIndex = index
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// properties
while index - occupyIndex < propertyLength! {
let resVariableByteInteger = decodeVariableByteInteger(data: connackData, offset: index)
index = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
case CocoaMQTTPropertyName.sessionExpiryInterval.rawValue:
let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint32.rawValue, offset: index)
sessionExpiryInterval = UInt32(comRes!.res)
index = comRes!.newOffset
case CocoaMQTTPropertyName.receiveMaximum.rawValue:
let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index)
receiveMaximum = UInt16(comRes!.res)
index = comRes!.newOffset
case CocoaMQTTPropertyName.maximumQoS.rawValue:
if index > connackData.count {
break
}
if connackData[index] & 0x01 > 0 {
maximumQoS = .qos0
} else {
maximumQoS = .qos1
}
index += 1
case CocoaMQTTPropertyName.retainAvailable.rawValue:
if index > connackData.count {
break
}
if connackData[index] & 0x01 > 0 {
retainAvailable = true
} else {
retainAvailable = false
}
index += 1
case CocoaMQTTPropertyName.maximumPacketSize.rawValue:
let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint32.rawValue, offset: index)
maximumPacketSize = UInt32(comRes!.res)
index = comRes!.newOffset
case CocoaMQTTPropertyName.assignedClientIdentifier.rawValue:
guard let result = unsignedByteToString(data: connackData, offset: index) else {
break
}
assignedClientIdentifier = result.resStr
index = result.newOffset
case CocoaMQTTPropertyName.topicAliasMaximum.rawValue:
let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index)
topicAliasMaximum = UInt16(comRes!.res)
index = comRes!.newOffset
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: connackData, offset: index) else {
break
}
reasonString = result.resStr
index = result.newOffset
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: connackData, offset: index) else {
break
}
key = keyRes.resStr
index = keyRes.newOffset
guard let valRes = unsignedByteToString(data: connackData, offset: index) else {
break
}
value = valRes.resStr
index = valRes.newOffset
userProperty![key!] = value
case CocoaMQTTPropertyName.wildcardSubscriptionAvailable.rawValue:
if index > connackData.count {
break
}
if connackData[index] & 0x01 > 0 {
wildcardSubscriptionAvailable = true
} else {
wildcardSubscriptionAvailable = false
}
index += 1
case CocoaMQTTPropertyName.subscriptionIdentifiersAvailable.rawValue:
if index > connackData.count {
break
}
if connackData[index] & 0x01 > 0 {
subscriptionIdentifiersAvailable = true
} else {
subscriptionIdentifiersAvailable = false
}
index += 1
case CocoaMQTTPropertyName.sharedSubscriptionAvailable.rawValue:
if index > connackData.count {
break
}
if connackData[index] & 0x01 > 0 {
sharedSubscriptionAvailable = true
} else {
sharedSubscriptionAvailable = false
}
index += 1
case CocoaMQTTPropertyName.serverKeepAlive.rawValue:
let comRes = integerCompute(data: connackData, formatType: formatInt.formatUint16.rawValue, offset: index)
serverKeepAlive = UInt16(comRes!.res)
index = comRes!.newOffset
case CocoaMQTTPropertyName.responseInformation.rawValue:
guard let valRes = unsignedByteToString(data: connackData, offset: index) else {
break
}
responseInformation = valRes.resStr
index = valRes.newOffset
case CocoaMQTTPropertyName.serverReference.rawValue:
guard let valRes = unsignedByteToString(data: connackData, offset: index) else {
break
}
serverReference = valRes.resStr
index = valRes.newOffset
case CocoaMQTTPropertyName.authenticationMethod.rawValue:
guard let valRes = unsignedByteToString(data: connackData, offset: index) else {
break
}
authenticationMethod = valRes.resStr
index = valRes.newOffset
case CocoaMQTTPropertyName.authenticationData.rawValue:
guard let valRes = unsignedByteToBinary(data: connackData, offset: index) else {
break
}
authenticationData = valRes.resStr
index = valRes.newOffset
default:
break
}
}
}
}
}

View File

@ -0,0 +1,101 @@
//
// MqttDecodePuback.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/3.
//
import Foundation
public class MqttDecodePubAck: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCode: CocoaMQTTPUBACKReasonCode?
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodePubAck(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
// 3.4.2.1 PUBACK Reason Code
// The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2.
if dataIndex + 1 > pubAckData.count {
return
}
guard let ack = CocoaMQTTPUBACKReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCode = ack
dataIndex += 1
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.4.2.2 PUBACK Properties
// 3.4.2.2.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.4.2.2.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.4.2.2.3 User Property
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
}
}

View File

@ -0,0 +1,101 @@
//
// MqttDecodePubComp.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/9.
//
import Foundation
public class MqttDecodePubComp: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCode: CocoaMQTTPUBCOMPReasonCode?
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodePubComp(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
// 3.6.2.1 PUBREL Reason Code
// The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2.
if dataIndex + 1 > pubAckData.count {
return
}
guard let ack = CocoaMQTTPUBCOMPReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCode = ack
dataIndex += 1
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.6.2.2 PUBREL Properties
// 3.6.2.2.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.6.2.2.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.6.2.2.3 User Property
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
}
}

View File

@ -0,0 +1,100 @@
//
// MqttDecodePubRec.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/4.
//
import Foundation
public class MqttDecodePubRec: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCode: CocoaMQTTPUBACKReasonCode?
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodePubRec(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
// 3.5.2.1 PUBREC Reason Code
// The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2.
if dataIndex + 1 > pubAckData.count {
return
}
guard let ack = CocoaMQTTPUBACKReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCode = ack
dataIndex += 1
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.5.2.2 PUBACK Properties
// 3.5.2.2.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.5.2.2.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.5.2.2.3 User Property
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
}
}

View File

@ -0,0 +1,101 @@
//
// MqttDecodePubRel.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/9.
//
import Foundation
public class MqttDecodePubRel: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCode: CocoaMQTTPUBRELReasonCode?
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodePubRel(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
// 3.6.2.1 PUBREL Reason Code
// The Reason Code and Property Length can be omitted if the Reason Code is 0x00 (Success) and there are no Properties. In this case the PUBACK has a Remaining Length of 2.
if dataIndex + 1 > pubAckData.count {
return
}
guard let ack = CocoaMQTTPUBRELReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCode = ack
dataIndex += 1
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.6.2.2 PUBREL Properties
// 3.6.2.2.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.6.2.2.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.6.2.2.3 User Property
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
}
}

View File

@ -0,0 +1,171 @@
//
// MqttDecodePublish.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/27.
//
import Foundation
public class MqttDecodePublish: NSObject {
// 3.3.2.3 PUBLISH Properties
// 3.3.2.3.1 Property Length
public var propertyLength: Int?
// 3.3.2.3.2 Payload Format Indicator
public var payloadFormatIndicator: PayloadFormatIndicator?
// 3.3.2.3.3 Message Expiry Interval
public var messageExpiryInterval: UInt32?
// 3.3.2.3.4 Topic Alias
public var topicAlias: UInt16?
// 3.3.2.3.5 Response Topic
public var responseTopic: String?
// 3.3.2.3.6 Correlation Data
public var correlationData: [UInt8]?
// 3.3.2.3.7 Property
public var userProperty: [String: String]?
// 3.3.2.3.8 Subscription Identifier
public var subscriptionIdentifier: Int = 0
// 3.3.2.3.9 Content Type
public var contentType: String?
// public var applicationMessage: [UInt8]?
// 3.3.2.1 Topic Name
public var topic: String = ""
// 3.3.2.2 Packet Identifier
public var packetIdentifier: UInt16?
public var mqtt5DataIndex = 0
public func decodePublish(fixedHeader: UInt8, publishData: [UInt8]) {
// Topic Name
// 3.3.2.1 Topic Name
var dataIndex = 0
guard let result = unsignedByteToString(data: publishData, offset: dataIndex) else {
return
}
self.topic = result.resStr
dataIndex = result.newOffset
mqtt5DataIndex = dataIndex
printDebug("topic = \(topic)")
guard let recQos = CocoaMQTTQoS(rawValue: (fixedHeader & 0b0000_0110) >> 1) else {
return
}
// 3.3.2.2 Packet Identifier
// Packet Identifier
if recQos == .qos1 || recQos == .qos2 {
let IdentifierResult = integerCompute(data: publishData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
packetIdentifier = UInt16(IdentifierResult!.res)
dataIndex = IdentifierResult!.newOffset
}
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.3.2.3.1 Property Length
// propertyLength
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: publishData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
mqtt5DataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + (propertyLength ?? 0) {
let resVariableByteInteger = decodeVariableByteInteger(data: publishData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.3.2.3.2 Payload Format Indicator
case CocoaMQTTPropertyName.payloadFormatIndicator.rawValue:
if publishData[dataIndex] & 0b0000_0001 > 0 {
payloadFormatIndicator = .utf8
} else {
payloadFormatIndicator = .unspecified
}
dataIndex += 1
// 3.3.2.3.3 Message Expiry Interval
case CocoaMQTTPropertyName.willExpiryInterval.rawValue:
let comRes = integerCompute(data: publishData, formatType: formatInt.formatUint32.rawValue, offset: dataIndex)
messageExpiryInterval = UInt32(comRes!.res)
dataIndex = comRes!.newOffset
// 3.3.2.3.4 Topic Alias
case CocoaMQTTPropertyName.topicAlias.rawValue:
let comRes = integerCompute(data: publishData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
topicAlias = UInt16(comRes!.res)
dataIndex = comRes!.newOffset
// 3.3.2.3.5 Response Topic
case CocoaMQTTPropertyName.responseTopic.rawValue:
guard let result = unsignedByteToString(data: publishData, offset: dataIndex) else {
break
}
responseTopic = result.resStr
dataIndex = result.newOffset
// 3.3.2.3.6 Correlation Data
case CocoaMQTTPropertyName.correlationData.rawValue:
guard let result = unsignedByteToBinary(data: publishData, offset: dataIndex) else {
break
}
correlationData = result.resStr
dataIndex = result.newOffset
// 3.3.2.3.7 User Property
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: publishData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: publishData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
if userProperty == nil {
userProperty = [:]
}
userProperty![key!] = value
// 3.3.2.3.8 Subscription Identifier
case CocoaMQTTPropertyName.subscriptionIdentifier.rawValue:
let valRes = decodeVariableByteInteger(data: publishData, offset: dataIndex)
subscriptionIdentifier = valRes.res
dataIndex = valRes.newOffset
// 3.3.2.3.9 Content Type
case CocoaMQTTPropertyName.contentType.rawValue:
guard let valRes = unsignedByteToString(data: publishData, offset: dataIndex) else {
break
}
contentType = valRes.resStr
dataIndex = valRes.newOffset
default:
return
}
}
}
}
}

View File

@ -0,0 +1,100 @@
//
// MqttDecodeSubAck.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/12.
//
import Foundation
public class MqttDecodeSubAck: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCodes: [CocoaMQTTSUBACKReasonCode] = []
// public var reasonCode: CocoaMQTTSUBACKReasonCode?
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodeSubAck(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.9.2.1 SUBACK Properties
// 3.9.2.1.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.9.2.1.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.9.2.1.3 User Property
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
if userProperty == nil {
userProperty = [:]
}
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
if dataIndex < totalCount {
while dataIndex < totalCount {
guard let reasonCode = CocoaMQTTSUBACKReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCodes.append(reasonCode)
dataIndex += 1
}
}
}
}

View File

@ -0,0 +1,96 @@
//
// MqttDecodeUnsubAck.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/8/16.
//
import Foundation
public class MqttDecodeUnsubAck: NSObject {
var totalCount = 0
var dataIndex = 0
var propertyLength: Int = 0
public var reasonCodes: [CocoaMQTTUNSUBACKReasonCode] = []
public var msgid: UInt16 = 0
public var reasonString: String?
public var userProperty: [String: String]?
public func decodeUnSubAck(fixedHeader: UInt8, pubAckData: [UInt8]) {
totalCount = pubAckData.count
dataIndex = 0
// msgid
let msgidResult = integerCompute(data: pubAckData, formatType: formatInt.formatUint16.rawValue, offset: dataIndex)
msgid = UInt16(msgidResult!.res)
dataIndex = msgidResult!.newOffset
var protocolVersion = ""
if let storage = CocoaMQTTStorage() {
protocolVersion = storage.queryMQTTVersion()
}
if protocolVersion == "5.0" {
// 3.11.2.1 UNSUBACK Properties
// 3.11.2.1.1 Property Length
let propertyLengthVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
propertyLength = propertyLengthVariableByteInteger.res
dataIndex = propertyLengthVariableByteInteger.newOffset
let occupyIndex = dataIndex
while dataIndex < occupyIndex + propertyLength {
let resVariableByteInteger = decodeVariableByteInteger(data: pubAckData, offset: dataIndex)
dataIndex = resVariableByteInteger.newOffset
let propertyNameByte = resVariableByteInteger.res
guard let propertyName = CocoaMQTTPropertyName(rawValue: UInt8(propertyNameByte)) else {
break
}
switch propertyName.rawValue {
// 3.11.2.1.2 Reason String
case CocoaMQTTPropertyName.reasonString.rawValue:
guard let result = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
reasonString = result.resStr
dataIndex = result.newOffset
// 3.11.2.1.3 User Property
case CocoaMQTTPropertyName.userProperty.rawValue:
var key: String?
var value: String?
guard let keyRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
key = keyRes.resStr
dataIndex = keyRes.newOffset
guard let valRes = unsignedByteToString(data: pubAckData, offset: dataIndex) else {
break
}
value = valRes.resStr
dataIndex = valRes.newOffset
userProperty![key!] = value
default:
return
}
}
}
if dataIndex < totalCount {
while dataIndex < totalCount {
guard let reasonCode = CocoaMQTTUNSUBACKReasonCode(rawValue: pubAckData[dataIndex]) else {
return
}
reasonCodes.append(reasonCode)
dataIndex += 1
}
}
}
}

View File

@ -0,0 +1,93 @@
//
// MqttPublishProperties.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/27.
//
import Foundation
public class MqttPublishProperties: NSObject {
// 3.3.2.3 PUBLISH Properties
// 3.3.2.3.1 Property Length
public var propertyLength: Int?
// 3.3.2.3.2 Payload Format Indicator
public var payloadFormatIndicator: PayloadFormatIndicator?
// 3.3.2.3.3 Message Expiry Interval
public var messageExpiryInterval: UInt32?
// 3.3.2.3.4 Topic Alias
public var topicAlias: UInt16?
// 3.3.2.3.5 Response Topic
public var responseTopic: String?
// 3.3.2.3.6 Correlation Data
public var correlationData: [UInt8]?
// 3.3.2.3.7 Property
public var userProperty: [String: String]?
// 3.3.2.3.8 Subscription Identifier
public var subscriptionIdentifier: UInt32?
// 3.3.2.3.9 Content Type
public var contentType: String?
public init(
propertyLength: Int? = nil,
payloadFormatIndicator: PayloadFormatIndicator? = nil,
messageExpiryInterval: UInt32? = nil,
topicAlias: UInt16? = nil,
responseTopic: String? = nil,
correlation: String? = nil,
userProperty: [String: String]? = nil,
subscriptionIdentifier: UInt32? = nil,
contentType: String? = nil
) {
self.propertyLength = propertyLength
self.payloadFormatIndicator = payloadFormatIndicator
self.messageExpiryInterval = messageExpiryInterval
self.topicAlias = topicAlias
self.responseTopic = responseTopic
self.correlationData = correlation?.bytesWithLength
self.userProperty = userProperty
self.subscriptionIdentifier = subscriptionIdentifier
self.contentType = contentType
}
public var properties: [UInt8] {
var properties = [UInt8]()
// 3.3.2.3.2 Payload Format Indicator
if let payloadFormatIndicator = self.payloadFormatIndicator {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.payloadFormatIndicator.rawValue, value: [payloadFormatIndicator.rawValue])
}
// 3.3.2.3.3 Message Expiry Interval
if let messageExpiryInterval = self.messageExpiryInterval {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.willExpiryInterval.rawValue, value: messageExpiryInterval.byteArrayLittleEndian)
}
// 3.3.2.3.4 Topic Alias
if let topicAlias = self.topicAlias {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.topicAlias.rawValue, value: topicAlias.hlBytes)
}
// 3.3.2.3.5 Response Topic
if let responseTopic = self.responseTopic {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.responseTopic.rawValue, value: responseTopic.bytesWithLength)
}
// 3.3.2.3.6 Correlation Data
if let correlationData = self.correlationData {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.correlationData.rawValue, value: correlationData)
}
// 3.3.2.3.7 Property Length User Property
if let userProperty = self.userProperty {
properties += userProperty.userPropertyBytes
}
// 3.3.2.3.8 Subscription Identifier
if let subscriptionIdentifier = self.subscriptionIdentifier,
let subscriptionIdentifier = beVariableByteInteger(subscriptionIdentifier) {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.subscriptionIdentifier.rawValue, value: subscriptionIdentifier)
}
// 3.3.2.3.9 Content Type
if let contentType = self.contentType {
properties += getMQTTPropertyData(type: CocoaMQTTPropertyName.contentType.rawValue, value: contentType.bytesWithLength)
}
return properties
}
}

View File

@ -0,0 +1,76 @@
//
// MqttSubscription.swift
// CocoaMQTT
//
// Created by liwei wang on 2021/7/15.
//
import Foundation
/// 3.8.3.1 Subscription Options
public class MqttSubscription {
public var topic: String
public var qos = CocoaMQTTQoS.qos1
public var noLocal: Bool = false
public var retainAsPublished: Bool = false
public var retainHandling: CocoaRetainHandlingOption = .sendOnSubscribe
public var subscriptionOptions: Bool = false
public init(topic: String) {
self.topic = topic
}
public init(topic: String, qos: CocoaMQTTQoS) {
self.topic = topic
self.qos = qos
}
var subscriptionData: [UInt8] {
var data = [UInt8]()
data += topic.bytesWithLength
var options: Int = 0
switch self.qos {
case .qos0:
options = options | 0b0000_0000
case .qos1:
options = options | 0b0000_0001
case .qos2:
options = options | 0b0000_0010
default:
printDebug("topicFilter qos failure")
}
switch self.noLocal {
case true:
options = options | 0b0000_0100
case false:
options = options | 0b0000_0000
}
switch self.retainAsPublished {
case true:
options = options | 0b0000_1000
case false:
options = options | 0b0000_0000
}
switch self.retainHandling {
case CocoaRetainHandlingOption.none:
options = options | 0b0010_0000
case CocoaRetainHandlingOption.sendOnlyWhenSubscribeIsNew:
options = options | 0b0001_0000
case CocoaRetainHandlingOption.sendOnSubscribe:
options = options | 0b0000_0000
}
if subscriptionOptions {
data += [UInt8(options)]
}
return data
}
}

View File

@ -0,0 +1,78 @@
//
// Copyright © 2022. All rights reserved.
//
import Foundation
/// A thread-safe dictionary
public class ThreadSafeDictionary<K: Hashable, V>: Collection {
private var dictionary: [K: V]
private let concurrentQueue: DispatchQueue
public var startIndex: Dictionary<K, V>.Index {
concurrentQueue.sync {
return self.dictionary.startIndex
}
}
public var endIndex: Dictionary<K, V>.Index {
concurrentQueue.sync {
return self.dictionary.endIndex
}
}
public init(label: String, dict: [K: V] = [K: V]()) {
self.dictionary = dict
concurrentQueue = DispatchQueue(label: label, attributes: .concurrent)
}
public func index(after i: Dictionary<K, V>.Index) -> Dictionary<K, V>.Index {
concurrentQueue.sync {
self.dictionary.index(after: i)
}
}
public subscript(key: K) -> V? {
get {
concurrentQueue.sync {
self.dictionary[key]
}
}
set(newValue) {
concurrentQueue.async(flags: .barrier) {[weak self] in
self?.dictionary[key] = newValue
}
}
}
public subscript(index: Dictionary<K, V>.Index) -> Dictionary<K, V>.Element {
concurrentQueue.sync {
self.dictionary[index]
}
}
@discardableResult
public func removeValue(forKey key: K) -> V? {
concurrentQueue.sync(flags: .barrier) {
self.dictionary.removeValue(forKey: key)
}
}
public func removeAll() {
concurrentQueue.async(flags: .barrier) {[weak self] in
self?.dictionary.removeAll()
}
}
public func snapshot() -> [K: V] {
concurrentQueue.sync {
dictionary
}
}
public func replace(with newDictionary: [K: V]) {
concurrentQueue.sync(flags: .barrier) {
dictionary = newDictionary
}
}
}

View File

@ -0,0 +1,73 @@
import Foundation
/// A thread-safe property wrapper that uses a concurrent dispatch queue for atomic operations.
///
/// This wrapper provides both synchronous and asynchronous access to a wrapped value in a
/// thread-safe manner using `DispatchQueue` with `.concurrent` attributes and `.barrier` writes.
///
/// - Important: Although this wrapper provides atomicity for access, it does not make the wrapped
/// value itself thread-safe if the type is not thread-safe. Avoid wrapping types that manage
/// internal shared state without their own synchronization.
///
/// - Example:
/// ```swift
/// @ConcurrentAtomic var counter: Int = 0
/// counter += 1
/// print(counter)
/// ```
@propertyWrapper
public class ConcurrentAtomic<T> {
private var _value: T
private let queue: DispatchQueue
/// Provides synchronous thread-safe access to the wrapped value.
///
/// - Note: Reads use `queue.sync` and can happen concurrently.
/// - Warning: Writes are done asynchronously with `.barrier`, so a following read may
/// not reflect the new value immediately.
public var wrappedValue: T {
get {
queue.sync { _value }
}
set {
queue.async(flags: .barrier) {
self._value = newValue
}
}
}
/// Returns the property wrapper instance itself for advanced usage, including mutation and transformation APIs.
public var projectedValue: ConcurrentAtomic<T> { self }
/// Initializes the property wrapper with an initial value and a custom queue label.
///
/// - Parameters:
/// - wrappedValue: The initial value to store.
/// - label: A debug label for the underlying `DispatchQueue`. Default is `"ConcurrentAtomic.Queue"`.
public init(wrappedValue: T, label: String = "ConcurrentAtomic.Queue") {
self._value = wrappedValue
self.queue = DispatchQueue(label: label, attributes: .concurrent)
}
/// Synchronously sets a new value in a thread-safe manner.
///
/// This uses `.barrier` to ensure the new value is fully written before continuing.
///
/// - Parameter newValue: The new value to be written.
public func setSync(_ newValue: T) {
queue.sync(flags: .barrier) {
self._value = newValue
}
}
/// Asynchronously mutates the wrapped value using a transform closure.
///
/// The mutation is performed with `.barrier`, ensuring it does not overlap with other reads or writes.
///
/// - Parameter transform: A closure that receives `inout` access to the wrapped value.
public func mutate(_ transform: @escaping (inout T) -> Void) {
queue.async(flags: .barrier) {
transform(&self._value)
}
}
}

12
Pods/Manifest.lock generated
View File

@ -11,6 +11,10 @@ PODS:
- CocoaLumberjack/Core (3.9.1)
- CocoaLumberjack/Swift (3.9.1):
- CocoaLumberjack/Core
- CocoaMQTT (2.2.5):
- CocoaMQTT/Core (= 2.2.5)
- CocoaMQTT/Core (2.2.5):
- MqttCocoaAsyncSocket (~> 1.0.8)
- Differentiator (5.0.0)
- GTCommonSDK (3.2.3.0):
- ZXSDK
@ -89,6 +93,7 @@ PODS:
- Moya/Core (= 15.0.0)
- Moya/Core (15.0.0):
- Alamofire (~> 5.0)
- MqttCocoaAsyncSocket (1.0.8)
- ObjectMapper (4.4.2)
- "OpenIMSDK (3.8.3+hotfix.3.1)":
- MJExtension
@ -174,6 +179,7 @@ DEPENDENCIES:
- AMapLocation
- AMapSearch
- CocoaLumberjack/Swift
- CocoaMQTT
- GYSDK
- HXPHPicker
- IQKeyboardManagerSwift
@ -215,6 +221,7 @@ SPEC REPOS:
- AMapLocation
- AMapSearch
- CocoaLumberjack
- CocoaMQTT
- Differentiator
- GTCommonSDK
- GYSDK
@ -236,6 +243,7 @@ SPEC REPOS:
- MJExtension
- MJRefresh
- Moya
- MqttCocoaAsyncSocket
- ObjectMapper
- OpenIMSDK
- OpenIMSDKCore
@ -277,6 +285,7 @@ SPEC CHECKSUMS:
AMapLocation: 6e44f50b044dc54c6b3dcb1dee5ffd6de2689e41
AMapSearch: 29224a399b56b17da1540e4312fc4d9dc37342bb
CocoaLumberjack: e4ba3b414dfca8c1916c6303d37f63b3a95134c6
CocoaMQTT: 1e2fa493d57045d66fb1eba2bb5ffb8d77039c60
Differentiator: e8497ceab83c1b10ca233716d547b9af21b9344d
GTCommonSDK: 238c6735add91e654f8564638854686ee3dcb4ac
GYSDK: db5f4b3aae8df06201be5e786076211ec11791be
@ -299,6 +308,7 @@ SPEC CHECKSUMS:
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
MqttCocoaAsyncSocket: 77d3b74f76228dd5a05d1f9526eab101d415b30c
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
@ -323,6 +333,6 @@ SPEC CHECKSUMS:
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
PODFILE CHECKSUM: 6ba8ada83ccc565c9bdcc418e9a936818640882c
PODFILE CHECKSUM: 861114200722c29adba98535aef6b0494d123b44
COCOAPODS: 1.16.2

35
Pods/MqttCocoaAsyncSocket/LICENSE.txt generated Normal file
View File

@ -0,0 +1,35 @@
This library is in the public domain.
However, not all organizations are allowed to use such a license.
For example, Germany doesn't recognize the Public Domain and one is not allowed to use libraries under such license (or similar).
Thus, the library is now dual licensed,
and one is allowed to choose which license they would like to use.
##################################################
License Option #1 :
##################################################
Public Domain
##################################################
License Option #2 :
##################################################
Software License Agreement (BSD License)
Copyright (c) 2017, Deusty, LLC
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Neither the name of Deusty LLC nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of Deusty LLC.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

121
Pods/MqttCocoaAsyncSocket/README.markdown generated Normal file
View File

@ -0,0 +1,121 @@
# CocoaAsyncSocket
[![Build Status](https://travis-ci.org/robbiehanson/CocoaAsyncSocket.svg?branch=master)](https://travis-ci.org/robbiehanson/CocoaAsyncSocket) [![Version Status](https://img.shields.io/cocoapods/v/CocoaAsyncSocket.svg?style=flat)](http://cocoadocs.org/docsets/CocoaAsyncSocket) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](http://img.shields.io/cocoapods/p/CocoaAsyncSocket.svg?style=flat)](http://cocoapods.org/?q=CocoaAsyncSocket) [![license Public Domain](https://img.shields.io/badge/license-Public%20Domain-orange.svg?style=flat)](https://en.wikipedia.org/wiki/Public_domain)
CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for macOS, iOS, and tvOS. The classes are described below.
## Installation
#### CocoaPods
Install using [CocoaPods](https://cocoapods.org) by adding this line to your Podfile:
````ruby
use_frameworks! # Add this if you are targeting iOS 8+ or using Swift
pod 'CocoaAsyncSocket'
````
#### Carthage
CocoaAsyncSocket is [Carthage](https://github.com/Carthage/Carthage) compatible. To include it add the following line to your `Cartfile`
```bash
github "robbiehanson/CocoaAsyncSocket" "master"
```
The project is currently configured to build for **iOS**, **tvOS** and **Mac**. After building with carthage the resultant frameworks will be stored in:
* `Carthage/Build/iOS/CocoaAsyncSocket.framework`
* `Carthage/Build/tvOS/CocoaAsyncSocket.framework`
* `Carthage/Build/Mac/CocoaAsyncSocket.framework`
Select the correct framework(s) and drag it into your project.
#### Swift Package Manager
Simply add the package dependency to your Package.swift and depend on "CocoaAsyncSocket" in the necessary targets:
```swift
dependencies: [
.package(url: "https://github.com/robbiehanson/CocoaAsyncSocket", from: "7.6.4")
]
```
#### Manual
You can also include it into your project by adding the source files directly, but you should probably be using a dependency manager to keep up to date.
### Importing
Using Objective-C:
```obj-c
// When using Clang Modules:
@import MqttCocoaAsyncSocket;
// or when not:
#import "GCDAsyncSocket.h" // for TCP
#import "GCDAsyncUdpSocket.h" // for UDP
```
Using Swift:
```swift
import MqttCocoaAsyncSocket
```
## TCP
**GCDAsyncSocket** is a TCP/IP socket networking library built atop Grand Central Dispatch. Here are the key features available:
- Native Objective-C, fully self-contained in one class.<br/>
_No need to muck around with sockets or streams. This class handles everything for you._
- Full delegate support<br/>
_Errors, connections, read completions, write completions, progress, and disconnections all result in a call to your delegate method._
- Queued non-blocking reads and writes, with optional timeouts.<br/>
_You tell it what to read or write, and it handles everything for you. Queueing, buffering, and searching for termination sequences within the stream - all handled for you automatically._
- Automatic socket acceptance.<br/>
_Spin up a server socket, tell it to accept connections, and it will call you with new instances of itself for each connection._
- Support for TCP streams over IPv4 and IPv6.<br/>
_Automatically connect to IPv4 or IPv6 hosts. Automatically accept incoming connections over both IPv4 and IPv6 with a single instance of this class. No more worrying about multiple sockets._
- Support for TLS / SSL<br/>
_Secure your socket with ease using just a single method call. Available for both client and server sockets._
- Fully GCD based and Thread-Safe<br/>
_It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._
## UDP
**GCDAsyncUdpSocket** is a UDP/IP socket networking library built atop Grand Central Dispatch. Here are the key features available:
- Native Objective-C, fully self-contained in one class.<br/>
_No need to muck around with low-level sockets. This class handles everything for you._
- Full delegate support.<br/>
_Errors, send completions, receive completions, and disconnections all result in a call to your delegate method._
- Queued non-blocking send and receive operations, with optional timeouts.<br/>
_You tell it what to send or receive, and it handles everything for you. Queueing, buffering, waiting and checking errno - all handled for you automatically._
- Support for IPv4 and IPv6.<br/>
_Automatically send/recv using IPv4 and/or IPv6. No more worrying about multiple sockets._
- Fully GCD based and Thread-Safe<br/>
_It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._
***
For those new(ish) to networking, it's recommended you **[read the wiki](https://github.com/robbiehanson/CocoaAsyncSocket/wiki)**.<br/>_Sockets might not work exactly like you think they do..._
**Still got questions?** Try the **[CocoaAsyncSocket Mailing List](https://groups.google.com/group/cocoaasyncsocket)**.
***
Love the project? Wanna buy me a ☕️&nbsp;&nbsp;? (or a 🍺&nbsp;&nbsp;😀&nbsp;):
[![donation-bitcoin](https://bitpay.com/img/donate-sm.png)](https://onename.com/robbiehanson)
[![donation-paypal](https://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2M8C699FQ8AW2)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4EB168A830EFA6136FA93357D1F1511A"
BuildableName = "CocoaMQTT.framework"
BlueprintName = "CocoaMQTT"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B017CC75E2704C686AA0A2203247D9C7"
BuildableName = "MqttCocoaAsyncSocket.framework"
BlueprintName = "MqttCocoaAsyncSocket"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -49,6 +49,11 @@
<key>isShown</key>
<false/>
</dict>
<key>CocoaMQTT.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
</dict>
<key>Differentiator.xcscheme</key>
<dict>
<key>isShown</key>
@ -214,6 +219,11 @@
<key>isShown</key>
<false/>
</dict>
<key>MqttCocoaAsyncSocket.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
</dict>
<key>ObjectMapper-Privacy.xcscheme</key>
<dict>
<key>isShown</key>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.2.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_CocoaMQTT : NSObject
@end
@implementation PodsDummy_CocoaMQTT
@end

View File

@ -0,0 +1,12 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

View File

@ -0,0 +1,16 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
FOUNDATION_EXPORT double CocoaMQTTVersionNumber;
FOUNDATION_EXPORT const unsigned char CocoaMQTTVersionString[];

View File

@ -0,0 +1,16 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "MqttCocoaAsyncSocket" -framework "Security"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/CocoaMQTT
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,6 @@
framework module CocoaMQTT {
umbrella header "CocoaMQTT-umbrella.h"
export *
module * { export * }
}

View File

@ -0,0 +1,16 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "MqttCocoaAsyncSocket" -framework "Security"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/CocoaMQTT
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_MqttCocoaAsyncSocket : NSObject
@end
@implementation PodsDummy_MqttCocoaAsyncSocket
@end

View File

@ -0,0 +1,12 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

View File

@ -0,0 +1,18 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "MGCDAsyncSocket.h"
#import "MGCDAsyncUdpSocket.h"
FOUNDATION_EXPORT double MqttCocoaAsyncSocketVersionNumber;
FOUNDATION_EXPORT const unsigned char MqttCocoaAsyncSocketVersionString[];

View File

@ -0,0 +1,13 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Security"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/MqttCocoaAsyncSocket
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,6 @@
framework module MqttCocoaAsyncSocket {
umbrella header "MqttCocoaAsyncSocket-umbrella.h"
export *
module * { export * }
}

View File

@ -0,0 +1,13 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Security"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/MqttCocoaAsyncSocket
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -87,6 +87,12 @@ Redistribution and use in source and binary forms, with or without modification,
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## CocoaMQTT
This project is dual licensed under the Eclipse Public License 1.0 and the
Eclipse Distribution License 1.0 as described in the epl-v10 and edl-v10 files.
## Differentiator
MIT License
@ -885,6 +891,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## MqttCocoaAsyncSocket
Public Domain License
The MqttCocoaAsyncSocket project is in the public domain.
The original TCP version (AsyncSocket) was created by Dustin Voss in January 2003.
Updated and maintained by Deusty LLC and the Apple development community.
## ObjectMapper
The MIT License (MIT)

View File

@ -140,6 +140,18 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>This project is dual licensed under the Eclipse Public License 1.0 and the
Eclipse Distribution License 1.0 as described in the epl-v10 and edl-v10 files.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>CocoaMQTT</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>MIT License
@ -1058,6 +1070,22 @@ SOFTWARE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Public Domain License
The MqttCocoaAsyncSocket project is in the public domain.
The original TCP version (AsyncSocket) was created by Dustin Voss in January 2003.
Updated and maintained by Deusty LLC and the Apple development community.
</string>
<key>License</key>
<string>public domain</string>
<key>Title</key>
<string>MqttCocoaAsyncSocket</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)

View File

@ -1,6 +1,7 @@
${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks.sh
${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework
${BUILT_PRODUCTS_DIR}/CocoaMQTT/CocoaMQTT.framework
${BUILT_PRODUCTS_DIR}/Differentiator/Differentiator.framework
${BUILT_PRODUCTS_DIR}/HXPHPicker/HXPHPicker.framework
${BUILT_PRODUCTS_DIR}/IQKeyboardCore/IQKeyboardCore.framework
@ -19,6 +20,7 @@ ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/Moya/Moya.framework
${BUILT_PRODUCTS_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework
${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework
${BUILT_PRODUCTS_DIR}/Popover/Popover.framework
${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework

View File

@ -1,5 +1,6 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaMQTT.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Differentiator.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HXPHPicker.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardCore.framework
@ -18,6 +19,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MarqueeLabel.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Moya.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MqttCocoaAsyncSocket.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjectMapper.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Popover.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework

View File

@ -1,6 +1,7 @@
${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks.sh
${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework
${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework
${BUILT_PRODUCTS_DIR}/CocoaMQTT/CocoaMQTT.framework
${BUILT_PRODUCTS_DIR}/Differentiator/Differentiator.framework
${BUILT_PRODUCTS_DIR}/HXPHPicker/HXPHPicker.framework
${BUILT_PRODUCTS_DIR}/IQKeyboardCore/IQKeyboardCore.framework
@ -19,6 +20,7 @@ ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/Moya/Moya.framework
${BUILT_PRODUCTS_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework
${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework
${BUILT_PRODUCTS_DIR}/Popover/Popover.framework
${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework

View File

@ -1,5 +1,6 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaMQTT.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Differentiator.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HXPHPicker.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardCore.framework
@ -18,6 +19,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MarqueeLabel.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Moya.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MqttCocoaAsyncSocket.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjectMapper.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Popover.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework

View File

@ -178,6 +178,7 @@ code_sign_if_enabled() {
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
install_framework "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework"
install_framework "${BUILT_PRODUCTS_DIR}/CocoaMQTT/CocoaMQTT.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Differentiator/Differentiator.framework"
install_framework "${BUILT_PRODUCTS_DIR}/HXPHPicker/HXPHPicker.framework"
install_framework "${BUILT_PRODUCTS_DIR}/IQKeyboardCore/IQKeyboardCore.framework"
@ -196,6 +197,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Moya/Moya.framework"
install_framework "${BUILT_PRODUCTS_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework"
install_framework "${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Popover/Popover.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework"
@ -221,6 +223,7 @@ fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework"
install_framework "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework"
install_framework "${BUILT_PRODUCTS_DIR}/CocoaMQTT/CocoaMQTT.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Differentiator/Differentiator.framework"
install_framework "${BUILT_PRODUCTS_DIR}/HXPHPicker/HXPHPicker.framework"
install_framework "${BUILT_PRODUCTS_DIR}/IQKeyboardCore/IQKeyboardCore.framework"
@ -239,6 +242,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Moya/Moya.framework"
install_framework "${BUILT_PRODUCTS_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework"
install_framework "${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Popover/Popover.framework"
install_framework "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework"

View File

@ -2,13 +2,13 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
ENABLE_USER_SCRIPT_SANDBOXING = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/Moya" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "${PODS_CONFIGURATION_BUILD_DIR}/Popover" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/AlipaySDK-iOS" "${PODS_ROOT}/OpenIMSDKCore/Framework" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_ROOT}/YYImage/Vendor" "${PODS_XCFRAMEWORKS_BUILD_DIR}/AlipaySDK-iOS" "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenIMSDKCore" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/Moya" "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "${PODS_CONFIGURATION_BUILD_DIR}/Popover" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/AlipaySDK-iOS" "${PODS_ROOT}/OpenIMSDKCore/Framework" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_ROOT}/YYImage/Vendor" "${PODS_XCFRAMEWORKS_BUILD_DIR}/AlipaySDK-iOS" "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenIMSDKCore" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack/CocoaLumberjack.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator/Differentiator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker/HXPHPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore/IQKeyboardCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification/IQKeyboardNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager/IQKeyboardReturnManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar/IQKeyboardToolbar.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager/IQKeyboardToolbarManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification/IQTextInputViewNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView/IQTextView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel/MarqueeLabel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Moya/Moya.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK/OpenIMSDK.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Popover/Popover.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa/RxCocoa.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources/RxDataSources.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay/RxRelay.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift/RxSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt/RxSwiftExt.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode/SGQRCode.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper/SwiftKeychainWrapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults/SwiftyUserDefaults.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView/TagListView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator/URLNavigator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser/YBImageBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack/CocoaLumberjack.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT/CocoaMQTT.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator/Differentiator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker/HXPHPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore/IQKeyboardCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification/IQKeyboardNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager/IQKeyboardReturnManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar/IQKeyboardToolbar.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager/IQKeyboardToolbarManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification/IQTextInputViewNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView/IQTextView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel/MarqueeLabel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Moya/Moya.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK/OpenIMSDK.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Popover/Popover.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa/RxCocoa.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources/RxDataSources.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay/RxRelay.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift/RxSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt/RxSwiftExt.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode/SGQRCode.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper/SwiftKeychainWrapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults/SwiftyUserDefaults.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView/TagListView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator/URLNavigator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser/YBImageBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"resolv" -l"sqlite3.0" -l"swiftCoreGraphics" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "Alamofire" -framework "AlipaySDK" -framework "AssetsLibrary" -framework "CFNetwork" -framework "CocoaLumberjack" -framework "Combine" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreText" -framework "Differentiator" -framework "ExternalAccessory" -framework "Foundation" -framework "GLKit" -framework "HXPHPicker" -framework "IQKeyboardCore" -framework "IQKeyboardManagerSwift" -framework "IQKeyboardNotification" -framework "IQKeyboardReturnManager" -framework "IQKeyboardToolbar" -framework "IQKeyboardToolbarManager" -framework "IQTextInputViewNotification" -framework "IQTextView" -framework "ImageIO" -framework "Kingfisher" -framework "KingfisherWebP" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "MarqueeLabel" -framework "Masonry" -framework "MobileCoreServices" -framework "Moya" -framework "ObjectMapper" -framework "OpenGLES" -framework "OpenIMCore" -framework "OpenIMSDK" -framework "Photos" -framework "PhotosUI" -framework "Popover" -framework "QuartzCore" -framework "RxCocoa" -framework "RxDataSources" -framework "RxRelay" -framework "RxSwift" -framework "RxSwiftExt" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SGQRCode" -framework "Security" -framework "SnapKit" -framework "SwiftDate" -framework "SwiftKeychainWrapper" -framework "SwiftyJSON" -framework "SwiftyUserDefaults" -framework "SystemConfiguration" -framework "TagListView" -framework "UIKit" -framework "URLNavigator" -framework "WebKit" -framework "WechatOpenSDK" -framework "YBImageBrowser" -framework "YYImage" -framework "libwebp" -weak_framework "AppTrackingTransparency" -weak_framework "Combine" -weak_framework "Network" -weak_framework "SwiftUI"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch" "-F${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "-F${PODS_CONFIGURATION_BUILD_DIR}/AlipaySDK-iOS" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "-F${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "-F${PODS_CONFIGURATION_BUILD_DIR}/GTCommonSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/GYSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "-F${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "-F${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/Moya" "-F${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDKCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/Popover" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "-F${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "-F${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework" "-F${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "-F${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZXSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"resolv" -l"sqlite3.0" -l"swiftCoreGraphics" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "Alamofire" -framework "AlipaySDK" -framework "AssetsLibrary" -framework "CFNetwork" -framework "CocoaLumberjack" -framework "CocoaMQTT" -framework "Combine" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreText" -framework "Differentiator" -framework "ExternalAccessory" -framework "Foundation" -framework "GLKit" -framework "HXPHPicker" -framework "IQKeyboardCore" -framework "IQKeyboardManagerSwift" -framework "IQKeyboardNotification" -framework "IQKeyboardReturnManager" -framework "IQKeyboardToolbar" -framework "IQKeyboardToolbarManager" -framework "IQTextInputViewNotification" -framework "IQTextView" -framework "ImageIO" -framework "Kingfisher" -framework "KingfisherWebP" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "MarqueeLabel" -framework "Masonry" -framework "MobileCoreServices" -framework "Moya" -framework "MqttCocoaAsyncSocket" -framework "ObjectMapper" -framework "OpenGLES" -framework "OpenIMCore" -framework "OpenIMSDK" -framework "Photos" -framework "PhotosUI" -framework "Popover" -framework "QuartzCore" -framework "RxCocoa" -framework "RxDataSources" -framework "RxRelay" -framework "RxSwift" -framework "RxSwiftExt" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SGQRCode" -framework "Security" -framework "SnapKit" -framework "SwiftDate" -framework "SwiftKeychainWrapper" -framework "SwiftyJSON" -framework "SwiftyUserDefaults" -framework "SystemConfiguration" -framework "TagListView" -framework "UIKit" -framework "URLNavigator" -framework "WebKit" -framework "WechatOpenSDK" -framework "YBImageBrowser" -framework "YYImage" -framework "libwebp" -weak_framework "AppTrackingTransparency" -weak_framework "Combine" -weak_framework "Network" -weak_framework "SwiftUI"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch" "-F${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "-F${PODS_CONFIGURATION_BUILD_DIR}/AlipaySDK-iOS" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT" "-F${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "-F${PODS_CONFIGURATION_BUILD_DIR}/GTCommonSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/GYSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "-F${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "-F${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/Moya" "-F${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket" "-F${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDKCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/Popover" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "-F${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "-F${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework" "-F${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "-F${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZXSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

View File

@ -2,13 +2,13 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
ENABLE_USER_SCRIPT_SANDBOXING = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/Moya" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "${PODS_CONFIGURATION_BUILD_DIR}/Popover" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/AlipaySDK-iOS" "${PODS_ROOT}/OpenIMSDKCore/Framework" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_ROOT}/YYImage/Vendor" "${PODS_XCFRAMEWORKS_BUILD_DIR}/AlipaySDK-iOS" "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenIMSDKCore" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/Moya" "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "${PODS_CONFIGURATION_BUILD_DIR}/Popover" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/AlipaySDK-iOS" "${PODS_ROOT}/OpenIMSDKCore/Framework" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_ROOT}/YYImage/Vendor" "${PODS_XCFRAMEWORKS_BUILD_DIR}/AlipaySDK-iOS" "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenIMSDKCore" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack/CocoaLumberjack.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator/Differentiator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker/HXPHPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore/IQKeyboardCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification/IQKeyboardNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager/IQKeyboardReturnManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar/IQKeyboardToolbar.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager/IQKeyboardToolbarManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification/IQTextInputViewNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView/IQTextView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel/MarqueeLabel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Moya/Moya.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK/OpenIMSDK.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Popover/Popover.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa/RxCocoa.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources/RxDataSources.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay/RxRelay.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift/RxSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt/RxSwiftExt.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode/SGQRCode.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper/SwiftKeychainWrapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults/SwiftyUserDefaults.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView/TagListView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator/URLNavigator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser/YBImageBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack/CocoaLumberjack.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT/CocoaMQTT.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Differentiator/Differentiator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker/HXPHPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore/IQKeyboardCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift/IQKeyboardManagerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification/IQKeyboardNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager/IQKeyboardReturnManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar/IQKeyboardToolbar.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager/IQKeyboardToolbarManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification/IQTextInputViewNotification.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQTextView/IQTextView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel/MarqueeLabel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Moya/Moya.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket/MqttCocoaAsyncSocket.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK/OpenIMSDK.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Popover/Popover.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa/RxCocoa.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources/RxDataSources.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxRelay/RxRelay.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwift/RxSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt/RxSwiftExt.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode/SGQRCode.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate/SwiftDate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper/SwiftKeychainWrapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON/SwiftyJSON.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults/SwiftyUserDefaults.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/TagListView/TagListView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator/URLNavigator.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser/YBImageBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"resolv" -l"sqlite3.0" -l"swiftCoreGraphics" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "Alamofire" -framework "AlipaySDK" -framework "AssetsLibrary" -framework "CFNetwork" -framework "CocoaLumberjack" -framework "Combine" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreText" -framework "Differentiator" -framework "ExternalAccessory" -framework "Foundation" -framework "GLKit" -framework "HXPHPicker" -framework "IQKeyboardCore" -framework "IQKeyboardManagerSwift" -framework "IQKeyboardNotification" -framework "IQKeyboardReturnManager" -framework "IQKeyboardToolbar" -framework "IQKeyboardToolbarManager" -framework "IQTextInputViewNotification" -framework "IQTextView" -framework "ImageIO" -framework "Kingfisher" -framework "KingfisherWebP" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "MarqueeLabel" -framework "Masonry" -framework "MobileCoreServices" -framework "Moya" -framework "ObjectMapper" -framework "OpenGLES" -framework "OpenIMCore" -framework "OpenIMSDK" -framework "Photos" -framework "PhotosUI" -framework "Popover" -framework "QuartzCore" -framework "RxCocoa" -framework "RxDataSources" -framework "RxRelay" -framework "RxSwift" -framework "RxSwiftExt" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SGQRCode" -framework "Security" -framework "SnapKit" -framework "SwiftDate" -framework "SwiftKeychainWrapper" -framework "SwiftyJSON" -framework "SwiftyUserDefaults" -framework "SystemConfiguration" -framework "TagListView" -framework "UIKit" -framework "URLNavigator" -framework "WebKit" -framework "WechatOpenSDK" -framework "YBImageBrowser" -framework "YYImage" -framework "libwebp" -weak_framework "AppTrackingTransparency" -weak_framework "Combine" -weak_framework "Network" -weak_framework "SwiftUI"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch" "-F${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "-F${PODS_CONFIGURATION_BUILD_DIR}/AlipaySDK-iOS" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "-F${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "-F${PODS_CONFIGURATION_BUILD_DIR}/GTCommonSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/GYSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "-F${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "-F${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/Moya" "-F${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDKCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/Popover" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "-F${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "-F${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework" "-F${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "-F${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZXSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"resolv" -l"sqlite3.0" -l"swiftCoreGraphics" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "Alamofire" -framework "AlipaySDK" -framework "AssetsLibrary" -framework "CFNetwork" -framework "CocoaLumberjack" -framework "CocoaMQTT" -framework "Combine" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMotion" -framework "CoreTelephony" -framework "CoreText" -framework "Differentiator" -framework "ExternalAccessory" -framework "Foundation" -framework "GLKit" -framework "HXPHPicker" -framework "IQKeyboardCore" -framework "IQKeyboardManagerSwift" -framework "IQKeyboardNotification" -framework "IQKeyboardReturnManager" -framework "IQKeyboardToolbar" -framework "IQKeyboardToolbarManager" -framework "IQTextInputViewNotification" -framework "IQTextView" -framework "ImageIO" -framework "Kingfisher" -framework "KingfisherWebP" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "MarqueeLabel" -framework "Masonry" -framework "MobileCoreServices" -framework "Moya" -framework "MqttCocoaAsyncSocket" -framework "ObjectMapper" -framework "OpenGLES" -framework "OpenIMCore" -framework "OpenIMSDK" -framework "Photos" -framework "PhotosUI" -framework "Popover" -framework "QuartzCore" -framework "RxCocoa" -framework "RxDataSources" -framework "RxRelay" -framework "RxSwift" -framework "RxSwiftExt" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SGQRCode" -framework "Security" -framework "SnapKit" -framework "SwiftDate" -framework "SwiftKeychainWrapper" -framework "SwiftyJSON" -framework "SwiftyUserDefaults" -framework "SystemConfiguration" -framework "TagListView" -framework "UIKit" -framework "URLNavigator" -framework "WebKit" -framework "WechatOpenSDK" -framework "YBImageBrowser" -framework "YYImage" -framework "libwebp" -weak_framework "AppTrackingTransparency" -weak_framework "Combine" -weak_framework "Network" -weak_framework "SwiftUI"
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch" "-F${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "-F${PODS_CONFIGURATION_BUILD_DIR}/AlipaySDK-iOS" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaLumberjack" "-F${PODS_CONFIGURATION_BUILD_DIR}/CocoaMQTT" "-F${PODS_CONFIGURATION_BUILD_DIR}/Differentiator" "-F${PODS_CONFIGURATION_BUILD_DIR}/GTCommonSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/GYSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/HXPHPicker" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManagerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardReturnManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbar" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardToolbarManager" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextInputViewNotification" "-F${PODS_CONFIGURATION_BUILD_DIR}/IQTextView" "-F${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "-F${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/MarqueeLabel" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/Moya" "-F${PODS_CONFIGURATION_BUILD_DIR}/MqttCocoaAsyncSocket" "-F${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/OpenIMSDKCore" "-F${PODS_CONFIGURATION_BUILD_DIR}/Popover" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxCocoa" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxDataSources" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxRelay" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/RxSwiftExt" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SGQRCode" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftDate" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftKeychainWrapper" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON" "-F${PODS_CONFIGURATION_BUILD_DIR}/SwiftyUserDefaults" "-F${PODS_CONFIGURATION_BUILD_DIR}/TagListView" "-F${PODS_CONFIGURATION_BUILD_DIR}/URLNavigator" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework" "-F${PODS_CONFIGURATION_BUILD_DIR}/YBImageBrowser" "-F${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZXSDK" "-F${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

View File

@ -188,6 +188,9 @@
30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; };
30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; };
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; };
30D87CDB2FDFA9EE00E958FD /* MQTTService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */; };
30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDC2FDFF07500E958FD /* InteractionView.swift */; };
30D87CDF2FDFF1A100E958FD /* QuickMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */; };
30DC18522FD009CD0041DCD1 /* VipExpenseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */; };
30DC18542FD00C4A0041DCD1 /* VipRechargeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */; };
30DC185A2FD11E7A0041DCD1 /* WebOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18562FD11E7A0041DCD1 /* WebOperations.swift */; };
@ -420,6 +423,9 @@
30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = "<group>"; };
30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = "<group>"; };
30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = "<group>"; };
30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTService.swift; sourceTree = "<group>"; };
30D87CDC2FDFF07500E958FD /* InteractionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionView.swift; sourceTree = "<group>"; };
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickMessageView.swift; sourceTree = "<group>"; };
30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipExpenseModel.swift; sourceTree = "<group>"; };
30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipRechargeVM.swift; sourceTree = "<group>"; };
30DC18552FD11E7A0041DCD1 /* NavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTitleView.swift; sourceTree = "<group>"; };
@ -472,6 +478,11 @@
path = lotties;
sourceTree = "<group>";
};
30D87CEF2FDFF52100E958FD /* TTGTagCollectionView */ = {
isa = PBXFileSystemSynchronizedRootGroup;
path = TTGTagCollectionView;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
@ -765,6 +776,7 @@
305A75282FCA8C7000227D26 /* Notification */,
305A752A2FCA8C7000227D26 /* Theme */,
305A752C2FCA8C7000227D26 /* URL */,
30D87CD52FDF9F1900E958FD /* MQTT */,
);
path = Manager;
sourceTree = "<group>";
@ -852,6 +864,8 @@
305A76292FCA8C7000227D26 /* HomeViewController.swift */,
305A798B2FCAB99300227D26 /* HomeViewModel.swift */,
30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */,
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */,
30D87CDC2FDFF07500E958FD /* InteractionView.swift */,
);
path = Home;
sourceTree = "<group>";
@ -1032,6 +1046,7 @@
305A767D2FCA8C7000227D26 /* UIKit */ = {
isa = PBXGroup;
children = (
30D87CEF2FDFF52100E958FD /* TTGTagCollectionView */,
305A76482FCA8C7000227D26 /* Alert */,
305A76502FCA8C7000227D26 /* EmptyDataSet */,
305A76542FCA8C7000227D26 /* HUD */,
@ -1174,6 +1189,14 @@
path = GroupInfo;
sourceTree = "<group>";
};
30D87CD52FDF9F1900E958FD /* MQTT */ = {
isa = PBXGroup;
children = (
30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */,
);
path = MQTT;
sourceTree = "<group>";
};
30DC18582FD11E7A0041DCD1 /* Controller */ = {
isa = PBXGroup;
children = (
@ -1313,6 +1336,7 @@
);
fileSystemSynchronizedGroups = (
3070777D2FD2A214004C37CC /* lotties */,
30D87CEF2FDFF52100E958FD /* TTGTagCollectionView */,
);
name = QuickLocation;
productName = QuickLocation;
@ -1457,6 +1481,7 @@
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */,
305A76902FCA8C7000227D26 /* UserAPI.swift in Sources */,
30EFF3DE2FDA982C00EB35D4 /* EmergencyContactAddVC.swift in Sources */,
30D87CDF2FDFF1A100E958FD /* QuickMessageView.swift in Sources */,
305A76912FCA8C7000227D26 /* Constant.swift in Sources */,
305A76922FCA8C7000227D26 /* LogUtils.swift in Sources */,
305A76932FCA8C7000227D26 /* AddImageCell.swift in Sources */,
@ -1620,6 +1645,7 @@
305A76FB2FCA8C7000227D26 /* EmptyDataSet.swift in Sources */,
305A76FC2FCA8C7000227D26 /* EmptyDataSetDelegate.swift in Sources */,
305A76FD2FCA8C7000227D26 /* EmptyDataSetSource.swift in Sources */,
30D87CDB2FDFA9EE00E958FD /* MQTTService.swift in Sources */,
30EFF3CD2FDA668A00EB35D4 /* MyProfileView.swift in Sources */,
305A76FE2FCA8C7000227D26 /* EmptyDataSetView.swift in Sources */,
30C4C0192FDBF094009215C1 /* RemoveMemberVC.swift in Sources */,
@ -1630,6 +1656,7 @@
305A77032FCA8C7000227D26 /* ProgressHUD.swift in Sources */,
305A77042FCA8C7000227D26 /* MXParallaxHeader.m in Sources */,
305A77052FCA8C7000227D26 /* MXScrollView.m in Sources */,
30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */,
30BAB8652FCD718A00C33B5C /* JoinGroupView.swift in Sources */,
305A77062FCA8C7000227D26 /* MXScrollViewController.m in Sources */,
305A77072FCA8C7000227D26 /* Helper.swift in Sources */,

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1572@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1572@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "interaction_header@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "interaction_header@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1951@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1951@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1947@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1947@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -79,6 +79,11 @@ final class MainTabBarController: UITabBarController {
guard let nav = selectedViewController as? UINavigationController else { return }
customTabBar.isHidden = nav.viewControllers.count > 1
}
/// / tabBar使
func setTabBarHidden(_ hidden: Bool) {
customTabBar.isHidden = hidden
}
}
// MARK: - QuickLocationTabBarDelegate

View File

@ -0,0 +1,257 @@
//
// MQTTService.swift
// QuickLocation
//
// Created by on 2026/6/12.
//
import Foundation
import CocoaMQTT
import UIKit
import _LocationEssentials
// MARK: - MQTT
///
enum MqttType: String, Codable {
case track = "track" // )
case disconnect = "disconnect"
case message = "message"
case join = "join" //
case leave = "leave" //
case dismiss = "dismiss" //
case kick = "kick" //
case signIn = "signin" //
case sos = "sos" //
case needTrack = "needtrack" //
case emote = "emote" //
}
///
struct Points: Codable {
let lat: Double
let lon: Double
let addr: String
let time: Int64 //
let speed: Double
let bearing: Double
let altitude: Double
let accuracy: Double
}
///
struct MqttLocation: Codable {
let battery: String
let points: [Points]
}
/// MQTT
struct MqttIncomingMessage: Decodable {
let type: String?
let data: MqttIncomingData?
let extra: String?
}
struct MqttIncomingData: Decodable {
let points: [Points]?
let battery: String?
}
// MARK: - MQTTService
/// MQTT 5.0
final class MQTTService: NSObject {
static let shared = MQTTService()
private var mqtt: CocoaMQTT5?
private var isConnected = false
// MARK: -
var onConnected: (() -> Void)?
var onDisconnected: (() -> Void)?
/// topicCallback
var onMessageReceived: ((CocoaMQTT5Message, UInt16, MqttPublishProperties) -> Void)?
/// topic
private var topicCallbacks: [String: (CocoaMQTT5Message) -> Void] = [:]
// MARK: -
private var host: String { "emqx.batiao8.com" }
private var port: UInt16 { 1883 }
/// clientID
private(set) var clientID: String = ""
private var userName = "batiao"
private var password = "Batiao12B"
private var topic = "smartdrive/"
override private init() {}
// MARK: -
func connect() {
guard !isConnected else { return }
if clientID.isEmpty {
clientID = "smartdrive_\(AppContextManager.shared.userId)"
}
let mqtt = CocoaMQTT5(clientID: clientID, host: host, port: port)
mqtt.username = userName
mqtt.password = password
mqtt.keepAlive = 60
mqtt.autoReconnect = true
mqtt.autoReconnectTimeInterval = 5
mqtt.delegate = self
mqtt.logLevel = .warning
self.mqtt = mqtt
_ = mqtt.connect()
}
// MARK: -
func disconnect() {
mqtt?.disconnect()
isConnected = false
}
// MARK: -
/// clientID
func updateClientID(_ newID: String) {
clientID = newID
disconnect()
connect()
}
// MARK: -
/// - Parameters:
/// - topic:
/// - qos:
/// - callback: topic
func subscribe(topic: String, qos: CocoaMQTTQoS = .qos1, callback: ((CocoaMQTT5Message) -> Void)? = nil) {
let subscription = MqttSubscription(topic: topic, qos: qos)
mqtt?.subscribe([subscription])
if let cb = callback {
topicCallbacks[topic] = cb
}
}
// MARK: -
func unsubscribe(topic: String) {
mqtt?.unsubscribe(topic)
topicCallbacks.removeValue(forKey: topic)
}
/// topic: smartdrive/<memberId>
func subscribeGroupMembers(_ memberIds: [String]) {
for id in memberIds {
subscribe(topic: "\(topic)\(id)")
}
}
///
func unsubscribeGroupMembers(_ memberIds: [String]) {
for id in memberIds {
mqtt?.unsubscribe("\(topic)\(id)")
}
}
// MARK: -
@discardableResult
func publish(topic: String, message: String, qos: CocoaMQTTQoS = .qos1) -> Int {
let properties = MqttPublishProperties()
return mqtt?.publish(topic, withString: message, qos: qos, DUP: false, retained: false, properties: properties) ?? -1
}
@discardableResult
func publish(topic: String, data: Data, qos: CocoaMQTTQoS = .qos1) -> Int {
let properties = MqttPublishProperties()
let message = CocoaMQTT5Message(topic: topic, payload: [UInt8](data))
return mqtt?.publish(message, DUP: false, retained: false, properties: properties) ?? -1
}
// MARK: -
/// Android
func reportLocation(lat: Double, lon: Double, addr: String,
speed: CLLocationSpeed, bearing: CLLocationDirection,
altitude: CLLocationDistance, accuracy: CLLocationAccuracy) {
let battery = UIDevice.current.batteryLevel > 0
? Int(UIDevice.current.batteryLevel * 100)
: 0
let point = Points(
lat: lat, lon: lon, addr: addr,
time: Int64(Date().timeIntervalSince1970 * 1000),
speed: speed, bearing: bearing,
altitude: altitude, accuracy: accuracy
)
let location = MqttLocation(battery: battery.string, points: [point])
guard let jsonData = try? JSONEncoder().encode(location),
let dataDict = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
else { return }
// data JSON
let payload: [String: Any] = [
"type": MqttType.track.rawValue,
"extra": "",
"data": dataDict
]
publish(topic: "\(topic)\(AppContextManager.shared.userId)", message: payload.toJsonString())
}
}
// MARK: - CocoaMQTT5Delegate
extension MQTTService: CocoaMQTT5Delegate {
func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?) {
isConnected = true
print("MQTT5 connected: \(ack)")
onConnected?()
}
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishMessage message: CocoaMQTT5Message, id: UInt16) {
print("MQTT5 published: \(message.topic)")
}
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishAck id: UInt16, pubAckData: MqttDecodePubAck?) {
print("MQTT5 publish ack: \(id)")
}
func mqtt5(_ mqtt5: CocoaMQTT5, didPublishRec id: UInt16, pubRecData: MqttDecodePubRec?) {}
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveMessage message: CocoaMQTT5Message, id: UInt16, publishData: MqttDecodePublish?) {
// topic
if let cb = topicCallbacks[message.topic] {
cb(message)
return
}
//
if let payload = message.string {
print("MQTT5 received on \(message.topic): \(payload)")
}
onMessageReceived?(message, id, MqttPublishProperties())
}
func mqtt5(_ mqtt5: CocoaMQTT5, didSubscribeTopics success: NSDictionary, failed: [String], subAckData: MqttDecodeSubAck?) {
print("MQTT5 subscribe success: \(success), failed: \(failed)")
}
func mqtt5(_ mqtt5: CocoaMQTT5, didUnsubscribeTopics topics: [String], unsubAckData: MqttDecodeUnsubAck?) {
print("MQTT5 unsubscribe: \(topics)")
}
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveDisconnectReasonCode reasonCode: CocoaMQTTDISCONNECTReasonCode) {}
func mqtt5(_ mqtt5: CocoaMQTT5, didReceiveAuthReasonCode reasonCode: CocoaMQTTAUTHReasonCode) {}
func mqtt5DidPing(_ mqtt5: CocoaMQTT5) {}
func mqtt5DidReceivePong(_ mqtt5: CocoaMQTT5) {}
func mqtt5DidDisconnect(_ mqtt5: CocoaMQTT5, withError err: Error?) {
isConnected = false
print("MQTT5 disconnected: \(err?.localizedDescription ?? "")")
onDisconnected?()
}
}

View File

@ -185,6 +185,8 @@ struct GroupMemberModel: Mappable, Equatable {
}
/// 线
var is_online: Bool = false
/// 线MQTT
var lastUpdateText: String = ""
///
var battery: String = ""
/// 线

View File

@ -17,6 +17,8 @@
#import "MXScrollView.h"
#import "MXScrollViewController.h"
#import "TTGTextTagCollectionView.h"
// Pop
#import "DLViewTransition.h"

View File

@ -30,7 +30,7 @@ class GroupInfoVC: BaseViewController {
rootView.groupIcon.image = model.groupIcon
rootView.groupNameLab.text = model.name
rootView.setupData(model)
rootView.applyBtn.rx.tap.subscribe(onNext: { _ in
self.requestOperateGroup()
}).disposed(by: disposeBag)

Some files were not shown because too many files have changed in this diff Show More