Merge pull request #214 from meshtastic/share_channel

Hook together SaveChannelQRCode View
This commit is contained in:
Garth Vander Houwen 2022-10-19 14:17:10 -07:00 committed by GitHub
commit 1fda757ffb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 95 deletions

View file

@ -195,13 +195,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
var peripheralName: String = peripheral.name ?? "Unknown"
let last4Code: String = (peripheral.name != nil ? String(peripheral.name!.suffix(4)) : "Unknown")
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
peripheralName = name
}
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: last4Code, longName: peripheralName, lastFourCode: last4Code, firmwareVersion: "Unknown", rssi: RSSI.intValue, bitrate: nil, channelUtilization: nil, airTime: nil, lastUpdate: Date(), peripheral: peripheral)
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: "????", longName: peripheralName, firmwareVersion: "Unknown", rssi: RSSI.intValue, lastUpdate: Date(), peripheral: peripheral)
let peripheralIndex = peripherals.firstIndex(where: { $0.id == newPeripheral.id })
if peripheralIndex != nil && newPeripheral.peripheral.state != CBPeripheralState.connected {
@ -325,14 +324,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let e = error {
MeshLogger.log("🚫 BLE didDiscoverCharacteristicsFor error by \(peripheral.name ?? "Unknown") \(e)")
}
guard let characteristics = service.characteristics else { return }
for characteristic in characteristics {
switch characteristic.uuid {
case TORADIO_UUID:
@ -340,13 +337,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
TORADIO_characteristic = characteristic
case FROMRADIO_UUID:
MeshLogger.log("✅ BLE did discover FROMRADIO characteristic for Meshtastic by \(peripheral.name ?? "Unknown")")
FROMRADIO_characteristic = characteristic
peripheral.readValue(for: FROMRADIO_characteristic)
case FROMNUM_UUID:
MeshLogger.log("✅ BLE did discover FROMNUM (Notify) characteristic for Meshtastic by \(peripheral.name ?? "Unknown")")
FROMNUM_characteristic = characteristic
peripheral.setNotifyValue(true, for: characteristic)
@ -368,7 +363,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
DFURESULT_characteristic = characteristic
case DFUREGION_UUID:
MeshLogger.log("✅ BLE did discover DFU Region characteristic for Meshtastic DFU by \(peripheral.name ?? "Unknown")")
DFUREGION_characteristic = characteristic
@ -377,7 +371,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
}
if (![FROMNUM_characteristic, TORADIO_characteristic].contains(nil)) {
sendWantConfig()
}
}
@ -395,7 +388,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
meshPacket.priority = MeshPacket.Priority.reliable
meshPacket.wantAck = true
var dataMessage = DataMessage()
dataMessage.payload = try! adminPacket.serializedData()
dataMessage.portnum = PortNum.adminApp
@ -517,10 +509,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
self.userSettings?.preferredNodeNum = myInfo?.myNodeNum ?? 0
if myInfo != nil {
self.connectedPeripheral.bitrate = myInfo!.bitrate
self.connectedPeripheral.num = myInfo!.myNodeNum
self.connectedPeripheral.firmwareVersion = myInfo!.firmwareVersion ?? "Unknown"
self.connectedPeripheral.name = myInfo!.bleName ?? "Unknown"
self.connectedPeripheral.longName = myInfo!.bleName ?? "Unknown"
@ -534,14 +523,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
let nodeInfo = nodeInfoPacket(nodeInfo: decodedInfo.nodeInfo, context: context!)
if nodeInfo != nil {
self.connectedPeripheral.channelUtilization = decodedInfo.nodeInfo.deviceMetrics.channelUtilization
self.connectedPeripheral.airTime = decodedInfo.nodeInfo.deviceMetrics.airUtilTx
if self.connectedPeripheral != nil && self.connectedPeripheral.num == nodeInfo!.num {
if nodeInfo!.user != nil {
connectedPeripheral.shortName = nodeInfo!.user!.shortName ?? "????"
connectedPeripheral.longName = nodeInfo!.user!.longName ?? "Unknown"
}
@ -947,7 +930,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
context!.rollback()
let nsError = error as NSError
MeshLogger.log("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
print()
}
}
return false
@ -1057,6 +1039,46 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
return false
}
public func connectToPreferredPeripheral() -> Bool {
var success = false
// Return false if we are not properly connected to a device, handle retry logic in the view for now
if connectedPeripheral == nil || connectedPeripheral!.peripheral.state != CBPeripheralState.connected {
self.disconnectPeripheral()
self.startScanning()
// Try and connect to the preferredPeripherial first
let preferredPeripheral = peripherals.filter({ $0.peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" }).first
if preferredPeripheral != nil && preferredPeripheral?.peripheral != nil {
connectTo(peripheral: preferredPeripheral!.peripheral)
success = true
}
} else if connectedPeripheral != nil && isSubscribed {
success = true
}
return success
}
public func saveChannelSet(base64UrlString: String) -> Bool {
if isConnected {
var decodedString = base64UrlString.base64urlToBase64()
if let decodedData = Data(base64Encoded: decodedString) {
do {
var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData)
print(channelSet)
} catch {
print("Invalid Meshtastic QR Code Link")
}
}
}
return false
}
public func saveUser(config: User, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
var adminPacket = AdminMessage()

View file

@ -24,12 +24,10 @@ struct MeshtasticAppleApp: App {
.environmentObject(bleManager)
.environmentObject(userSettings)
.sheet(isPresented: $saveChannels) {
SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL")
SaveChannelQRCode(channelSetLink: channelSettings ?? "Empty Channel URL", bleManager: bleManager)
.presentationDetents([.medium, .large])
.presentationDragIndicator(.visible)
}
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
print("URL received \(userActivity)")

View file

@ -7,27 +7,19 @@ struct Peripheral: Identifiable {
var name: String
var shortName: String
var longName: String
var lastFourCode: String
var firmwareVersion: String
var rssi: Int
var bitrate: Float?
var channelUtilization: Float?
var airTime: Float?
var lastUpdate: Date
var peripheral: CBPeripheral
init(id: String, num: Int64, name: String, shortName: String, longName: String, lastFourCode: String, firmwareVersion: String, rssi: Int, bitrate: Float?, channelUtilization: Float?, airTime: Float?, lastUpdate: Date, peripheral: CBPeripheral) {
init(id: String, num: Int64, name: String, shortName: String, longName: String, firmwareVersion: String, rssi: Int, lastUpdate: Date, peripheral: CBPeripheral) {
self.id = id
self.num = num
self.name = name
self.shortName = shortName
self.longName = longName
self.lastFourCode = lastFourCode
self.firmwareVersion = firmwareVersion
self.rssi = rssi
self.bitrate = bitrate
self.channelUtilization = channelUtilization
self.airTime = airTime
self.lastUpdate = lastUpdate
self.peripheral = peripheral
}

View file

@ -216,6 +216,10 @@ struct OEMStore {
/// Use this font for the OEM text.
var oemText: String = String()
///
/// The default device encryption key, 16 or 32 byte
var oemAesKey: Data = Data()
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@ -408,6 +412,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
3: .standard(proto: "oem_icon_bits"),
4: .standard(proto: "oem_font"),
5: .standard(proto: "oem_text"),
6: .standard(proto: "oem_aes_key"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -421,6 +426,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
case 3: try { try decoder.decodeSingularBytesField(value: &self.oemIconBits) }()
case 4: try { try decoder.decodeSingularEnumField(value: &self.oemFont) }()
case 5: try { try decoder.decodeSingularStringField(value: &self.oemText) }()
case 6: try { try decoder.decodeSingularBytesField(value: &self.oemAesKey) }()
default: break
}
}
@ -442,6 +448,9 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
if !self.oemText.isEmpty {
try visitor.visitSingularStringField(value: self.oemText, fieldNumber: 5)
}
if !self.oemAesKey.isEmpty {
try visitor.visitSingularBytesField(value: self.oemAesKey, fieldNumber: 6)
}
try unknownFields.traverse(visitor: &visitor)
}
@ -451,6 +460,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
if lhs.oemIconBits != rhs.oemIconBits {return false}
if lhs.oemFont != rhs.oemFont {return false}
if lhs.oemText != rhs.oemText {return false}
if lhs.oemAesKey != rhs.oemAesKey {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}

View file

@ -101,13 +101,10 @@ struct Connect: View {
if node != nil {
Text("Num: \(String(node!.num))")
Text("Short Name: \(bleManager.connectedPeripheral.shortName)")
Text("Long Name: \(bleManager.connectedPeripheral.longName)")
Text("Unique Code: \(bleManager.connectedPeripheral.lastFourCode)")
Text("Short Name: \(node?.user?.shortName ?? "????")")
Text("Long Name: \(node?.user?.longName ?? "Unknown")")
Text("Max Channels: \(String(node!.myInfo!.maxChannels))")
Text("Bitrate: \(String(format: "%.2f", bleManager.connectedPeripheral.bitrate ?? 0.00))")
Text("Ch. Utilization: \(String(format: "%.2f", bleManager.connectedPeripheral.channelUtilization ?? 0.00))")
Text("Air Time: \(String(format: "%.2f", bleManager.connectedPeripheral.airTime ?? 0.00))")
Text("Bitrate: \(String(format: "%.2f", node?.myInfo?.bitrate ?? 0.00))")
Text("BLE RSSI: \(bleManager.connectedPeripheral.rssi)")
}

View file

@ -16,7 +16,6 @@ struct DeviceConfig: View {
@State private var isPresentingNodeDBResetConfirm = false
@State private var isPresentingFactoryResetConfirm = false
@State private var isPresentingSaveConfirm = false
@State var initialLoad: Bool = true
@State var hasChanges = false
@State var deviceRole = 0
@ -166,17 +165,11 @@ struct DeviceConfig: View {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
if self.initialLoad{
self.bleManager.context = context
self.deviceRole = Int(node?.deviceConfig?.role ?? 0)
self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true)
self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false
self.hasChanges = false
self.initialLoad = false
}
self.bleManager.context = context
self.deviceRole = Int(node?.deviceConfig?.role ?? 0)
self.serialEnabled = (node?.deviceConfig?.serialEnabled ?? true)
self.debugLogEnabled = node?.deviceConfig?.debugLogEnabled ?? false
self.hasChanges = false
}
.onChange(of: deviceRole) { newRole in

View file

@ -14,7 +14,6 @@ struct SerialConfig: View {
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var initialLoad: Bool = true
@State var hasChanges = false
@State var enabled = false
@ -115,7 +114,7 @@ struct SerialConfig: View {
Label("Save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false))
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
@ -140,7 +139,6 @@ struct SerialConfig: View {
let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
@ -155,26 +153,20 @@ struct SerialConfig: View {
.navigationBarItems(trailing:
ZStack {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context
self.enabled = node?.serialConfig?.enabled ?? false
self.echo = node?.serialConfig?.echo ?? false
self.rxd = Int(node?.serialConfig?.rxd ?? 0)
self.txd = Int(node?.serialConfig?.txd ?? 0)
self.baudRate = Int(node?.serialConfig?.baudRate ?? 0)
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
self.mode = Int(node?.serialConfig?.mode ?? 0)
self.hasChanges = false
if self.initialLoad{
self.bleManager.context = context
self.enabled = node?.serialConfig?.enabled ?? false
self.echo = node?.serialConfig?.echo ?? false
self.rxd = Int(node?.serialConfig?.rxd ?? 0)
self.txd = Int(node?.serialConfig?.txd ?? 0)
self.baudRate = Int(node?.serialConfig?.baudRate ?? 0)
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
self.mode = Int(node?.serialConfig?.mode ?? 0)
self.hasChanges = false
self.initialLoad = false
}
}
.onChange(of: enabled) { newEnabled in

View file

@ -7,8 +7,10 @@
import SwiftUI
struct SaveChannelQRCode: View {
var channelHash: String
var channelSetLink: String
var bleManager: BLEManager
@State var connectedToDevice = false
var body: some View {
VStack {
Text("Save Channel Settings?")
@ -17,32 +19,23 @@ struct SaveChannelQRCode: View {
.foregroundColor(.gray)
.font(.callout)
.padding()
Text(channelHash)
.font(.caption2)
.foregroundColor(.gray)
.padding()
Button {
} label: {
Label("Save", systemImage: "square.and.arrow.down")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
}
.onChange(of: channelHash) { newSettings in
var decodedString = newSettings.base64urlToBase64()
if let decodedData = Data(base64Encoded: decodedString) {
do {
var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData)
print(channelSet)
} catch {
print("Invalid Meshtastic QR Code Link")
Button {
let success = bleManager.saveChannelSet(base64UrlString: channelSetLink)
} label: {
Label("Save", systemImage: "square.and.arrow.down")
}
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
.disabled(!connectedToDevice)
}
.onAppear {
connectedToDevice = bleManager.connectToPreferredPeripheral()
}
}
}