mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Setup MQTT client proxy connection
This commit is contained in:
parent
9c04add62a
commit
a11d41c137
3 changed files with 220 additions and 0 deletions
|
|
@ -121,6 +121,7 @@
|
|||
DDCDC6CB29481FCC004C1DDA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDCDC6CD29481FCC004C1DDA /* Localizable.strings */; };
|
||||
DDCE4E2C2869F92900BE9F8F /* UserConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */; };
|
||||
DDD3BBD5292D763200D609B3 /* MeshtasticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD3BBD4292D763200D609B3 /* MeshtasticTests.swift */; };
|
||||
DDD43FE32A78C8900083A3E9 /* MqttClientProxyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD43FE22A78C8900083A3E9 /* MqttClientProxyManager.swift */; };
|
||||
DDD6EEAF29BC024700383354 /* Firmware.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD6EEAE29BC024700383354 /* Firmware.swift */; };
|
||||
DDD94A502845C8F5004A87A0 /* DateTimeText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */; };
|
||||
DDD9E4E4284B208E003777C5 /* UserEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD9E4E3284B208E003777C5 /* UserEntityExtension.swift */; };
|
||||
|
|
@ -323,6 +324,7 @@
|
|||
DDCDC6CE294821AD004C1DDA /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserConfig.swift; sourceTree = "<group>"; };
|
||||
DDD3BBD4292D763200D609B3 /* MeshtasticTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeshtasticTests.swift; sourceTree = "<group>"; };
|
||||
DDD43FE22A78C8900083A3E9 /* MqttClientProxyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MqttClientProxyManager.swift; sourceTree = "<group>"; };
|
||||
DDD6EEAE29BC024700383354 /* Firmware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Firmware.swift; sourceTree = "<group>"; };
|
||||
DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeText.swift; sourceTree = "<group>"; };
|
||||
DDD9E4E3284B208E003777C5 /* UserEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserEntityExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -710,6 +712,7 @@
|
|||
DDC2E1A526CEB32B0042C5E4 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDD43FE12A78C86B0083A3E9 /* Mqtt */,
|
||||
DDB75A122A0593CD006ED576 /* Map */,
|
||||
DDAF8C5226EB1DF10058C060 /* BLEManager.swift */,
|
||||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */,
|
||||
|
|
@ -736,6 +739,14 @@
|
|||
path = Persistence;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDD43FE12A78C86B0083A3E9 /* Mqtt */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDD43FE22A78C8900083A3E9 /* MqttClientProxyManager.swift */,
|
||||
);
|
||||
path = Mqtt;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDDB443E29F79A9400EE2349 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1032,6 +1043,7 @@
|
|||
DD3CC6C228EB9D4900FA9159 /* UpdateCoreData.swift in Sources */,
|
||||
DDE0F7C5295F77B700B8AAB3 /* AppSettingsEnums.swift in Sources */,
|
||||
DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */,
|
||||
DDD43FE32A78C8900083A3E9 /* MqttClientProxyManager.swift in Sources */,
|
||||
DDDB444629F8A96500EE2349 /* Character.swift in Sources */,
|
||||
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,
|
||||
DDB6ABDB28B0AC6000384BA1 /* DistanceText.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import CoreData
|
|||
import CoreBluetooth
|
||||
import SwiftUI
|
||||
import MapKit
|
||||
import CocoaMQTT
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Meshtastic BLE Device Manager
|
||||
|
|
@ -37,6 +38,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
var positionTimer: Timer?
|
||||
var lastPosition: CLLocationCoordinate2D?
|
||||
let emptyNodeNum: UInt32 = 4294967295
|
||||
let mqttManager = MqttClientProxyManager.shared
|
||||
/* Meshtastic Service Details */
|
||||
var TORADIO_characteristic: CBCharacteristic!
|
||||
var FROMRADIO_characteristic: CBCharacteristic!
|
||||
|
|
@ -573,6 +575,22 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
RunLoop.current.add(positionTimer!, forMode: .common)
|
||||
}
|
||||
}
|
||||
/// MQTT Client Proxy
|
||||
if true {
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(connectedPeripheral.num))
|
||||
do {
|
||||
let fetchedNodeInfo = try context?.fetch(fetchNodeInfoRequest) as? [NodeInfoEntity] ?? []
|
||||
if fetchedNodeInfo.count == 1 && fetchedNodeInfo[0].mqttConfig != nil {
|
||||
//Subscribe to Mqtt Client Proxy if enabled
|
||||
mqttManager.connectFromConfigSettings(config: fetchedNodeInfo[0].mqttConfig!)
|
||||
|
||||
}
|
||||
} catch {
|
||||
print("Failed to find a node info for the connected node")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
190
Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift
Normal file
190
Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
//
|
||||
// MQTTManager.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 7/31/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CocoaMQTT
|
||||
|
||||
class MqttClientProxyManager {
|
||||
|
||||
enum ConnectionStatus {
|
||||
case connecting
|
||||
case connected
|
||||
case disconnecting
|
||||
case disconnected
|
||||
case error
|
||||
case none
|
||||
}
|
||||
|
||||
enum MqttQos: Int {
|
||||
case atMostOnce = 0
|
||||
case atLeastOnce = 1
|
||||
case exactlyOnce = 2
|
||||
}
|
||||
|
||||
static let shared = MqttClientProxyManager()
|
||||
private static let defaultKeepAliveInterval: Int32 = 60
|
||||
weak var delegate: CocoaMQTTDelegate?
|
||||
var status = ConnectionStatus.none
|
||||
var mqttClient: CocoaMQTT?
|
||||
|
||||
private init() {
|
||||
|
||||
}
|
||||
|
||||
func connectFromConfigSettings(config: MQTTConfigEntity) {
|
||||
|
||||
let defaultServerAddress = "mqtt.meshtastic.org"
|
||||
let defaultServerPort = 1883
|
||||
//let
|
||||
var host = config.address
|
||||
if host == nil || host!.isEmpty {
|
||||
host = defaultServerAddress
|
||||
}
|
||||
|
||||
if let host = host {
|
||||
let port = defaultServerPort
|
||||
let username = config.username
|
||||
let password = config.password
|
||||
connect(host: host, port: port, username: username, password: password, cleanSession: true)
|
||||
}
|
||||
}
|
||||
|
||||
func connect(host: String, port: Int, username: String?, password: String?, cleanSession: Bool) {
|
||||
|
||||
let clientId = "MeshtasticAppleMqttProxy-" + String(ProcessInfo().processIdentifier)
|
||||
status = .connecting
|
||||
mqttClient = CocoaMQTT(clientID: clientId, host: host, port: UInt16(port))
|
||||
|
||||
if let mqttClient = mqttClient {
|
||||
|
||||
mqttClient.username = username
|
||||
mqttClient.password = password
|
||||
mqttClient.keepAlive = 60
|
||||
mqttClient.cleanSession = cleanSession
|
||||
mqttClient.logLevel = .debug
|
||||
mqttClient.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")
|
||||
mqttClient.autoReconnect = true
|
||||
|
||||
mqttClient.delegate = self
|
||||
let success = mqttClient.connect()
|
||||
if !success {
|
||||
status = .error
|
||||
}
|
||||
|
||||
} else {
|
||||
status = .error
|
||||
}
|
||||
}
|
||||
|
||||
func subscribe(topic: String, qos: MqttQos) {
|
||||
let qos = CocoaMQTTQoS(rawValue :UInt8(qos.rawValue))!
|
||||
mqttClient?.subscribe(topic, qos: qos)
|
||||
}
|
||||
|
||||
func unsubscribe(topic: String) {
|
||||
mqttClient?.unsubscribe(topic)
|
||||
}
|
||||
|
||||
func publish(message: String, topic: String, qos: MqttQos) {
|
||||
let qos = CocoaMQTTQoS(rawValue :UInt8(qos.rawValue))!
|
||||
mqttClient?.publish(topic, withString: message, qos: qos)
|
||||
}
|
||||
|
||||
func disconnect() {
|
||||
//MqttSettings.shared.isConnected = false
|
||||
|
||||
if let client = mqttClient {
|
||||
status = .disconnecting
|
||||
client.disconnect()
|
||||
} else {
|
||||
status = .disconnected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension MqttClientProxyManager: CocoaMQTTDelegate {
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
|
||||
completionHandler(true)
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
|
||||
|
||||
print("didConnectAck: \(ack)")
|
||||
if ack == .accept {
|
||||
//delegate?.onMqttConnected()
|
||||
|
||||
// if let topic = mqttSettings.subscribeTopic, mqttSettings.isSubscribeEnabled {
|
||||
// self.subscribe(topic: topic, qos: mqttSettings.subscribeQos)
|
||||
// }
|
||||
} else {
|
||||
// Connection error
|
||||
var errorDescription = "Unknown Error"
|
||||
switch ack {
|
||||
case .accept:
|
||||
errorDescription = "No Error"
|
||||
case .unacceptableProtocolVersion:
|
||||
errorDescription = "Proto ver"
|
||||
case .identifierRejected:
|
||||
errorDescription = "Invalid Id"
|
||||
case .serverUnavailable:
|
||||
errorDescription = "Invalid Server"
|
||||
case .badUsernameOrPassword:
|
||||
errorDescription = "Invalid Credentials"
|
||||
case .notAuthorized:
|
||||
errorDescription = "Authorization Error"
|
||||
default:
|
||||
errorDescription = "Unknown Error"
|
||||
}
|
||||
print(errorDescription)
|
||||
//delegate?.onMqttError(message: errorDescription)
|
||||
|
||||
//self.disconnect() // Stop reconnecting
|
||||
//mqttSettings.isConnected = false // Disable automatic connect on start
|
||||
}
|
||||
|
||||
self.status = ack == .accept ? ConnectionStatus.connected : ConnectionStatus.error // Set AFTER sending onMqttError (so the delegate can detect that was an error while stablishing connection)
|
||||
|
||||
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
|
||||
print("didPublishMessage")
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
|
||||
print("didPublishAck")
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
|
||||
if let string = message.string {
|
||||
print("didReceiveMessage: \(string) from topic: \(message.topic)")
|
||||
} else {
|
||||
print("didReceiveMessage but message is not defined")
|
||||
}
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {
|
||||
print("didSubscribeTopics: \(success.allKeys.count) topics. failed: \(failed.count) topics")
|
||||
}
|
||||
|
||||
func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) {
|
||||
print("didUnsubscribeTopics: \(topics.joined(separator: ", "))")
|
||||
}
|
||||
|
||||
func mqttDidPing(_ mqtt: CocoaMQTT) {
|
||||
print("mqttDidPing")
|
||||
}
|
||||
|
||||
func mqttDidReceivePong(_ mqtt: CocoaMQTT) {
|
||||
print("mqttDidReceivePong")
|
||||
}
|
||||
|
||||
func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) {
|
||||
print("mqttDidDisconnect")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue