V 1.35 Connected Peripheral and MyInfo bugs

This commit is contained in:
Garth Vander Houwen 2021-12-24 21:50:10 -08:00
parent 92c61f199f
commit a8d08c0b9f
8 changed files with 183 additions and 104 deletions

View file

@ -695,7 +695,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.33;
MARKETING_VERSION = 1.35;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
@ -722,7 +722,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.33;
MARKETING_VERSION = 1.35;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;

View file

@ -80,22 +80,6 @@
landmarkType = "24">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "77F5CE1E-8BA3-4831-8A0D-6CEE16E9E8FD"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "808"
endingLineNumber = "808"
landmarkName = "sendMessage(message:toUserNum:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@ -106,8 +90,8 @@
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "894"
endingLineNumber = "894"
startingLineNumber = "897"
endingLineNumber = "897"
landmarkName = "sendMessage(message:toUserNum:)"
landmarkType = "7">
</BreakpointContent>
@ -115,15 +99,15 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "6D12B6E1-7FB9-466C-94FA-1BCA5CB64261"
uuid = "04619ED9-EF12-49A5-9AEF-C115B206581C"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "505"
endingLineNumber = "505"
startingLineNumber = "469"
endingLineNumber = "469"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
@ -131,15 +115,15 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "332E0378-DE65-4ED3-ACB0-668EB8D62DE8"
uuid = "F25765DD-CBAA-4892-8EE8-A632C79D42F0"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "405"
endingLineNumber = "405"
startingLineNumber = "466"
endingLineNumber = "466"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>

View file

@ -25,7 +25,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
@Published var peripherals = [Peripheral]()
@Published var connectedPeripheral: Peripheral!
//@Published var connectedNode: NodeInfoEntity!
@Published var lastConnectedPeripheral: String
@Published var lastConnectionError: String
@ -220,6 +219,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
} catch {
print("💥 Fetch NodeInfo Failed")
if meshLoggingEnabled { MeshLogger.log("💥 Fetch NodeInfo Failed") }
}
lastConnectedPeripheral = peripheral.identifier.uuidString
@ -257,8 +257,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
// We will try and re-connect to this device
lastConnectionError = "🚫 \(e.localizedDescription) The app will automatically reconnect to the preferred radio if it reappears within 10 seconds."
if peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" {
if meshLoggingEnabled { MeshLogger.log("BLE Reconnecting: \(peripheral.name ?? "Unknown")") }
print("BLE Reconnecting: \(peripheral.name ?? "Unknown")")
if meshLoggingEnabled { MeshLogger.log(" BLE Reconnecting: \(peripheral.name ?? "Unknown")") }
print(" BLE Reconnecting: \(peripheral.name ?? "Unknown")")
self.connectTo(peripheral: peripheral)
}
} else if errorCode == 7 { // CBError.Code.peripheralDisconnected The specified device has disconnected from us.
@ -340,7 +340,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
peripheral.readValue(for: FROMRADIO_characteristic)
case FROMNUM_UUID:
print("FROMNUM (Notify) characteristic OK")
print("FROMNUM (Notify) characteristic OK")
if meshLoggingEnabled { MeshLogger.log("✅ BLE did discover FROMNUM (Notify) characteristic for Meshtastic by \(peripheral.name ?? "Unknown")") }
FROMNUM_characteristic = characteristic
peripheral.setNotifyValue(true, for: characteristic)
@ -390,14 +390,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
var decodedInfo = FromRadio()
decodedInfo = try! FromRadio(serializedData: characteristic.value!)
print("Print DecodedInfo")
print(decodedInfo)
//print("Print DecodedInfo")
//print(decodedInfo)
// MyInfo Data
if decodedInfo.myInfo.myNodeNum != 0 {
print("💾 Save a CoreData MyInfoEntity")
let fetchMyInfoRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(decodedInfo.myInfo.myNodeNum))
@ -413,6 +411,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
myInfo.messageTimeoutMsec = Int32(bitPattern: decodedInfo.myInfo.messageTimeoutMsec)
myInfo.minAppVersion = Int32(bitPattern: decodedInfo.myInfo.minAppVersion)
myInfo.maxChannels = Int32(bitPattern: decodedInfo.myInfo.maxChannels)
connectedPeripheral.num = myInfo.myNodeNum
connectedPeripheral.firmwareVersion = myInfo.firmwareVersion ?? "Unknown"
}
else {
@ -439,17 +440,14 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
} catch {
print("💥 Fetch MyInfo Error")
print("💥 Fetch MyInfo Error")
}
}
// NodeInfo Data
if decodedInfo.nodeInfo.num != 0 {
print("💾 Save a CoreData NodeInfoEntity")
let fetchNodeRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeRequest.predicate = NSPredicate(format: "num == %lld", Int64(decodedInfo.nodeInfo.num))
@ -469,12 +467,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if self.connectedPeripheral != nil && self.connectedPeripheral.num == newNode.id {
newNode.bleName = self.connectedPeripheral.name
} else {
let userIdLast4: String = String(decodedInfo.nodeInfo.user.id.suffix(4))
newNode.bleName = "Meshtastic_" + userIdLast4
newNode.bleName = self.connectedPeripheral.peripheral.name
if decodedInfo.nodeInfo.hasUser {
connectedPeripheral.name = decodedInfo.nodeInfo.user.longName
connectedPeripheral.longName = decodedInfo.nodeInfo.user.longName
connectedPeripheral.shortName = decodedInfo.nodeInfo.user.shortName
}
}
if decodedInfo.nodeInfo.hasUser {
@ -486,6 +485,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
newUser.shortName = decodedInfo.nodeInfo.user.shortName
newUser.macaddr = decodedInfo.nodeInfo.user.macaddr
newUser.hwModel = String(describing: decodedInfo.nodeInfo.user.hwModel).uppercased()
newUser.team = (String(describing: decodedInfo.nodeInfo.user.team))
newNode.user = newUser
}
@ -530,6 +530,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
fetchedNode[0].user!.longName = decodedInfo.nodeInfo.user.longName
fetchedNode[0].user!.shortName = decodedInfo.nodeInfo.user.shortName
fetchedNode[0].user!.hwModel = String(describing: decodedInfo.nodeInfo.user.hwModel).uppercased()
fetchedNode[0].user!.team = (String(describing: decodedInfo.nodeInfo.user.team))
}
let position = PositionEntity(context: context!)
@ -625,9 +626,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if decodedInfo.packet.to == broadcastNodeNum && fetchedUsers.count == 1 {
// Save the broadcast user if it does not exist
let bcu: UserEntity = UserEntity(context: context!)
bcu.shortName = "BC"
bcu.longName = "Broadcast"
bcu.shortName = "ALL"
bcu.longName = "Broadcast (^all)"
bcu.hwModel = "UNSET"
bcu.num = Int64(broadcastNodeNum)
bcu.userId = "BROADCASTNODE"
@ -693,12 +695,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
return
}
do {
// print(decodedInfo.packet.decoded.payload)
try context!.save()
if meshLoggingEnabled {
MeshLogger.log("💾 Updated NodeInfo SNR and Time from Node Info App Packet For: \(Int64(decodedInfo.nodeInfo.num))")
}
if meshLoggingEnabled { MeshLogger.log("💾 Updated NodeInfo SNR and Time from Node Info App Packet For: \(Int64(decodedInfo.nodeInfo.num))")}
print("💾 Updated NodeInfo SNR and Time from Packet For: \(fetchedNode[0].num)")
} catch {
@ -714,8 +714,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
print("💥 Error Fetching NodeInfoEntity for NODEINFO_APP")
}
print(decodedInfo.packet.decoded.payload)
} else if decodedInfo.packet.decoded.portnum == PortNum.positionApp {
let fetchNodePositionRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
@ -728,7 +726,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if fetchedNode.count == 1 {
fetchedNode[0].id = Int64(decodedInfo.packet.from)
fetchedNode[0].num = Int64(decodedInfo.packet.from)
print(decodedInfo.packet.decoded.payload)
if(decodedInfo.packet.rxTime == 0) {
fetchedNode[0].lastHeard = Date()
@ -830,9 +827,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
success = false
} else if message.count < 1 {
// Don's send an empty message
print("Don't Send an Empty Message")
// Don't send an empty message
print("🚫 Don't Send an Empty Message")
success = false
} else {
let fromUserNum:Int64 = self.connectedPeripheral.num
@ -846,7 +845,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if fetchedUsers.isEmpty {
print("Message Users Not Found, Fail")
print("🚫 Message Users Not Found, Fail")
success = false
}
else if fetchedUsers.count >= 1 {
@ -860,8 +859,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if newMessage.toUser == nil {
let bcu: UserEntity = UserEntity(context: context!)
bcu.shortName = "BC"
bcu.longName = "Broadcast"
bcu.shortName = "ALL"
bcu.longName = "Broadcast (^all)"
bcu.hwModel = "UNSET"
bcu.num = Int64(broadcastNodeNum)
bcu.userId = "BROADCASTNODE"
@ -888,6 +887,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
toRadio.packet = meshPacket
let binaryData: Data = try! toRadio.serializedData()
if meshLoggingEnabled { MeshLogger.log("📲 New message sent to \(newMessage.toUser?.longName! ?? "Unknown")") }
print("📲 New message sent to \(newMessage.toUser?.longName! ?? "Unknown")")
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
do {
@ -903,7 +906,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
context!.rollback()
let nsError = error as NSError
print("Unresolved error \(nsError)")
print("🚫 Unresolved error \(nsError)")
}
}
}

View file

@ -58,6 +58,7 @@
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="shortName" attributeType="String"/>
<attribute name="team" optional="YES" attributeType="String"/>
<attribute name="userId" attributeType="String"/>
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
@ -68,6 +69,6 @@
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="149"/>
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="149"/>
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
<element name="UserEntity" positionX="0" positionY="144" width="128" height="164"/>
<element name="UserEntity" positionX="0" positionY="144" width="128" height="179"/>
</elements>
</model>

View file

@ -21,22 +21,22 @@ struct MeshtasticClientApp: App {
.onChange(of: scenePhase) { (newScenePhase) in
switch newScenePhase {
case .background:
print(" Scene is in the background")
do {
try persistenceController.container.viewContext.save()
print("Saved viewContext when the app went to the background.")
print("💾 Saved CoreData ViewContext when the app went to the background.")
} catch {
print("Failed to save viewContext when the app goes to the background.")
print("💥 Failed to save viewContext when the app goes to the background.")
}
print("Scene is in the background")
case .inactive:
print("Scene is inactive")
print(" Scene is inactive")
case .active:
print("Scene is active")
print(" Scene is active")
@unknown default:
print("Apple must have changed something")
print("💥 Apple must have changed something")
}
}
}

View file

@ -8,6 +8,7 @@ struct ContentView: View {
@State private var selection: Tab = .ble
enum Tab {
case contacts
case messages
case map
case ble
@ -18,6 +19,14 @@ struct ContentView: View {
var body: some View {
TabView(selection: $selection) {
// Contacts()
// .tabItem {
// Label("Contacts", systemImage: "person.crop.circle")
// .symbolRenderingMode(.hierarchical)
// .symbolVariant(.none)
//
// }
// .tag(Tab.contacts)
Channels()
.tabItem {
Label("Messages", systemImage: "text.bubble")

View file

@ -8,8 +8,91 @@
import SwiftUI
struct Contacts: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@FetchRequest(
sortDescriptors: [NSSortDescriptor(key: "longName", ascending: true)],
animation: .default)
private var users: FetchedResults<UserEntity>
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
NavigationView {
List(users) { user in
if user.receivedMessages?.count ?? 0 > 0 {
let mostRecent = user.receivedMessages?.lastObject as! MessageEntity
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64(mostRecent.messageTimestamp)))
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0
HStack {
VStack {
CircleText(text: user.shortName ?? "???", color: Color.blue)
}
VStack {
HStack (alignment: .bottom){
VStack {
Text(user.longName ?? "Unknown").font(.headline)
}
VStack {
if lastMessageDay == currentDay {
Text(lastMessageTime, style: .time )
.font(.caption)
.foregroundColor(.gray)
} else if ( lastMessageDay == (currentDay - 1)) {
Text("Yesterday")
.font(.callout)
.foregroundColor(.gray)
} else if ( lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) ) {
Text(lastMessageTime, style: .date)
} else {
Text(lastMessageTime, style: .date)
}
}.frame(maxWidth: .infinity, alignment: .trailing)
}
.listRowSeparator(.hidden).frame(height: 5)
HStack (alignment: .top) {
Text(mostRecent.messagePayload ?? "EMPTY MESSSAGE")
.frame(height: 60)
.truncationMode(.tail)
}
}
}.padding(10)
} else {
HStack {
VStack {
CircleText(text: user.shortName ?? "???", color: Color.blue)
}
VStack {
HStack{
VStack {
Text(user.longName ?? "Unknown").font(.title3)
}
}
}
}.padding()
}
//NavigationLink(note.title, destination: NoteEditor(id: note.id))
}
.navigationTitle("Contacts")
}
}
}

View file

@ -175,7 +175,7 @@ struct NodeDetail: View {
}
}.padding()
if node.positions?.count ?? 0 > 0 {
if node.positions?.count ?? 0 > 1 {
Divider()
@ -193,52 +193,51 @@ struct NodeDetail: View {
ForEach(node.positions!.array as! [PositionEntity], id: \.self) { (mappin: PositionEntity) in
//if mappin.coordinate != nil {
if mappin.coordinate != nil {
VStack {
HStack {
Image(systemName: "mappin.and.ellipse").foregroundColor(.accentColor) //.font(.subheadline)
Text("Lat/Long:").font(.caption)
Text("\(String(mappin.latitude ?? 0)) \(String(mappin.longitude ?? 0))")
.foregroundColor(.gray)
.font(.caption)
HStack {
Text("Altitude:")
.font(.caption)
Text("\(String(mappin.altitude))m")
.foregroundColor(.gray)
.font(.caption)
Image(systemName: "mappin.and.ellipse").foregroundColor(.accentColor) //.font(.subheadline)
Text("Lat/Long:").font(.caption)
Text("\(String(mappin.latitude ?? 0)) \(String(mappin.longitude ?? 0))")
.foregroundColor(.gray)
.font(.caption)
Text("Altitude:")
.font(.caption)
Text("\(String(mappin.altitude))m")
.foregroundColor(.gray)
.font(.caption)
}
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.subheadline)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Time:")
.font(.caption)
Text("\(mappin.time!, style: .date) \(mappin.time!, style: .time)")
.foregroundColor(.gray)
.font(.caption)
Divider()
Text("Battery").font(.caption).fixedSize()
Text(String(mappin.batteryLevel) + "%")
.font(.caption)
.foregroundColor(.gray)
.symbolRenderingMode(.hierarchical)
}
}
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.subheadline)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("Time:")
.font(.caption)
Text("\(mappin.time!, style: .date) \(mappin.time!, style: .time)")
.foregroundColor(.gray)
.font(.caption)
Divider()
Text("Battery").font(.caption).fixedSize()
Text(String(mappin.batteryLevel) + "%")
.font(.caption)
.foregroundColor(.gray)
.symbolRenderingMode(.hierarchical)
}
}
.padding(1)
Divider()
//}
}
}
.padding(.bottom, 5) // Without some padding here there is a transparent contentview bug
}
}
}
.navigationTitle(node.user!.longName ?? "Unknown")