Merge branch 'main' into jpirihi-dev

This commit is contained in:
Garth Vander Houwen 2021-12-25 00:22:04 -08:00 committed by GitHub
commit 64dcd4b1ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 307 additions and 123 deletions

View file

@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
C9483F6D2773017500998F6B /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9483F6C2773017500998F6B /* MapView.swift */; };
C9A7BC1027759A9600760B50 /* PositionAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */; };
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */; };
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2E65252767A01F00E45FC5 /* NodeDetail.swift */; };
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3CD26F103C600029299 /* NodeList.swift */; };
@ -25,6 +26,7 @@
DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */; };
DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8169FE272476C700F4AB02 /* LogDocument.swift */; };
DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD836AE626F6B38600ABCC23 /* Connect.swift */; };
DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD882F5C2772E4640005BF05 /* Contacts.swift */; };
DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860B26F684AF00DC5189 /* BatteryIcon.swift */; };
DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860D26F69BAE00DC5189 /* NodeMap.swift */; };
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; };
@ -71,6 +73,7 @@
/* Begin PBXFileReference section */
C9483F6C2773017500998F6B /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = "<group>"; };
C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionAnnotationView.swift; sourceTree = "<group>"; };
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMessageList.swift; sourceTree = "<group>"; };
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
DD2E65252767A01F00E45FC5 /* NodeDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeDetail.swift; sourceTree = "<group>"; };
DD47E3CD26F103C600029299 /* NodeList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeList.swift; sourceTree = "<group>"; };
@ -86,6 +89,7 @@
DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshLog.swift; sourceTree = "<group>"; };
DD8169FE272476C700F4AB02 /* LogDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogDocument.swift; sourceTree = "<group>"; };
DD836AE626F6B38600ABCC23 /* Connect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connect.swift; sourceTree = "<group>"; };
DD882F5C2772E4640005BF05 /* Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contacts.swift; sourceTree = "<group>"; };
DD90860A26F645B700DC5189 /* MeshtasticClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MeshtasticClient.entitlements; sourceTree = "<group>"; };
DD90860B26F684AF00DC5189 /* BatteryIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIcon.swift; sourceTree = "<group>"; };
DD90860D26F69BAE00DC5189 /* NodeMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMap.swift; sourceTree = "<group>"; };
@ -315,6 +319,8 @@
children = (
DD47E3DA26F3901A00029299 /* Channels.swift */,
DD47E3DC26F390A000029299 /* Messages.swift */,
DD882F5C2772E4640005BF05 /* Contacts.swift */,
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */,
);
path = Messages;
sourceTree = "<group>";
@ -527,8 +533,10 @@
DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */,
DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */,
DD9D8F2F2764403B00080993 /* Meshtastic.xcdatamodeld in Sources */,
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */,
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,
C9A7BC1027759A9600760B50 /* PositionAnnotationView.swift in Sources */,
DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */,
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */,
@ -715,7 +723,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.32;
MARKETING_VERSION = 1.36;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
@ -742,7 +750,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.32;
MARKETING_VERSION = 1.36;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;

View file

@ -83,15 +83,15 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "BD16DE86-365A-47B2-8DBB-340D5A835D76"
uuid = "04619ED9-EF12-49A5-9AEF-C115B206581C"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "492"
endingLineNumber = "492"
startingLineNumber = "469"
endingLineNumber = "469"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
@ -99,15 +99,31 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "77F5CE1E-8BA3-4831-8A0D-6CEE16E9E8FD"
uuid = "F25765DD-CBAA-4892-8EE8-A632C79D42F0"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "809"
endingLineNumber = "809"
startingLineNumber = "466"
endingLineNumber = "466"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "679F6F7F-E126-4725-A682-BC8129C0CCB9"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "806"
endingLineNumber = "806"
landmarkName = "sendMessage(message:toUserNum:)"
landmarkType = "7">
</BreakpointContent>
@ -115,16 +131,16 @@
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "B9045E7F-D63F-4540-B984-60F820809762"
uuid = "1756397A-4451-4B94-8EB1-0B19AD444C9E"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "MeshtasticClient/Helpers/BLEManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "893"
endingLineNumber = "893"
landmarkName = "sendMessage(message:toUserNum:)"
startingLineNumber = "608"
endingLineNumber = "608"
landmarkName = "peripheral(_:didUpdateValueFor:error:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>

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
@ -55,7 +54,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
// MARK: init BLEManager
override init() {
self.meshLoggingEnabled = UserDefaults.standard.object(forKey: "meshActivityLog") as? Bool ?? false
self.meshLoggingEnabled = true // UserDefaults.standard.object(forKey: "meshActivityLog") as? Bool ?? true
self.lastConnectedPeripheral = ""
self.lastConnectionError = ""
super.init()
@ -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,8 +340,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
peripheral.readValue(for: FROMRADIO_characteristic)
case FROMNUM_UUID:
print("FROMNUM (Notify) characteristic OK")
if meshLoggingEnabled { MeshLogger.log("BLE did discover FROMNUM (Notify) characteristic for Meshtastic by \(peripheral.name ?? "Unknown")") }
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))
@ -457,7 +455,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
let fetchedNode = try context?.fetch(fetchNodeRequest) as! [NodeInfoEntity]
// Not Found Insert
if fetchedNode.isEmpty {
if fetchedNode.isEmpty && decodedInfo.nodeInfo.hasUser {
let newNode = NodeInfoEntity(context: context!)
newNode.id = Int64(decodedInfo.nodeInfo.num)
@ -469,12 +467,14 @@ 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
connectedPeripheral.num = Int64(decodedInfo.nodeInfo.num)
}
}
if decodedInfo.nodeInfo.hasUser {
@ -486,6 +486,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
}
@ -517,7 +518,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
print("💥 Fetch MyInfo Error")
}
} else {
} else if decodedInfo.nodeInfo.hasUser {
fetchedNode[0].id = Int64(decodedInfo.nodeInfo.num)
fetchedNode[0].num = Int64(decodedInfo.nodeInfo.num)
@ -530,6 +531,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!)
@ -600,17 +602,15 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
// Handle assorted app packets
if decodedInfo.packet.id != 0 {
print("Handle a Packet")
do {
//!!!: Switch Messages Tab to coredata
// Text Message App - Primary Broadcast Channel
if decodedInfo.packet.decoded.portnum == PortNum.textMessageApp {
if let messageText = String(bytes: decodedInfo.packet.decoded.payload, encoding: .utf8) {
print("Message Text: \(messageText)")
if meshLoggingEnabled { MeshLogger.log("BLE FROMRADIO received for text message app \(messageText)") }
print("💬 BLE FROMRADIO received for text message app \(messageText)")
if meshLoggingEnabled { MeshLogger.log("💬 BLE FROMRADIO received for text message app \(messageText)") }
let messageUsers:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
messageUsers.predicate = NSPredicate(format:"num IN %@", [decodedInfo.packet.to, decodedInfo.packet.from])
@ -624,13 +624,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
newMessage.messageTimestamp = Int32(bitPattern: decodedInfo.packet.rxTime)
newMessage.receivedACK = false
newMessage.direction = "IN"
//newMessage.toUser = Int64(decodedInfo.packet.to)
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 = "Primary - Broadcast"
bcu.hwModel = "UNSET"
bcu.num = Int64(broadcastNodeNum)
bcu.userId = "BROADCASTNODE"
@ -647,7 +647,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
do {
try context!.save()
print("Saved a new message for \(decodedInfo.packet.id)")
print("💾 Saved a new message for \(decodedInfo.packet.id)")
if meshLoggingEnabled { MeshLogger.log("💾 Saved a new message for \(decodedInfo.packet.id)") }
// Create an iOS Notification for the received message and schedule it immediately
let manager = LocalNotificationManager()
@ -660,19 +661,19 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
content: messageText)
]
manager.schedule()
if meshLoggingEnabled { MeshLogger.log("iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown") \(messageText)") }
if meshLoggingEnabled { MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown") \(messageText)") }
} catch {
context!.rollback()
let nsError = error as NSError
print("Failed to save new MessageEntity \(nsError)")
print("💥 Failed to save new MessageEntity \(nsError)")
}
} catch {
print("Fetch Message To and From Users Error")
print("💥 Fetch Message To and From Users Error")
}
}
} else if decodedInfo.packet.decoded.portnum == PortNum.nodeinfoApp {
@ -695,29 +696,25 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
return
}
do {
// print(decodedInfo.packet.decoded.payload)
try context!.save()
if meshLoggingEnabled {
MeshLogger.log("MESH PACKET 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)")
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 {
context!.rollback()
let nsError = error as NSError
print("Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
print("💥 Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
}
} catch {
print("Error Fetching NodeInfoEntity for NODEINFO_APP")
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")
@ -730,7 +727,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()
@ -760,32 +756,33 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
context!.rollback()
let nsError = error as NSError
print("Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
print("💥 Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
}
} catch {
print("Error Fetching NodeInfoEntity for NODEINFO_APP")
print("💥 Error Fetching NodeInfoEntity for NODEINFO_APP")
}
} else if decodedInfo.packet.decoded.portnum == PortNum.adminApp {
if meshLoggingEnabled { MeshLogger.log("MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("Admin App Packet")
print(try decodedInfo.packet.jsonString())
if meshLoggingEnabled { MeshLogger.log("🚨 MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("🚨 MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())")
} else if decodedInfo.packet.decoded.portnum == PortNum.routingApp {
if meshLoggingEnabled { MeshLogger.log("MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("Routing App Packet")
print(try decodedInfo.packet.jsonString())
if meshLoggingEnabled { MeshLogger.log("🚨 MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("🚨 MESH PACKET received for Routing App UNHANDLED \(try decodedInfo.packet.jsonString())")
} else {
if meshLoggingEnabled { MeshLogger.log("MESH PACKET received for Other App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("Other App Packet")
print(try decodedInfo.packet.jsonString())
if meshLoggingEnabled { MeshLogger.log("🚨 MESH PACKET received for Other App UNHANDLED \(try decodedInfo.packet.jsonString())") }
print("🚨 MESH PACKET received for Other App UNHANDLED \(try decodedInfo.packet.jsonString())")
}
} catch {
if meshLoggingEnabled { MeshLogger.log("Fatal Error: Failed to decode json") }
fatalError("Failed to decode json")
if meshLoggingEnabled { MeshLogger.log("⚰️ Fatal Error: Failed to decode json") }
print("⚰️ Fatal Error: Failed to decode json")
}
}
@ -798,8 +795,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
default:
if meshLoggingEnabled { MeshLogger.log("Unhandled Characteristic UUID: \(characteristic.uuid)") }
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
if meshLoggingEnabled { MeshLogger.log("🚨 Unhandled Characteristic UUID: \(characteristic.uuid)") }
print("🚨 Unhandled Characteristic UUID: \(characteristic.uuid)")
}
peripheral.readValue(for: FROMRADIO_characteristic)
}
@ -826,12 +823,16 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
connectTo(peripheral: lastConnectedPeripheral!.peripheral)
}
}
print("Failed in the top message condition")
print("🚫 Message Send Failed, not properly connected to \(lastConnectedPeripheral)")
if meshLoggingEnabled { MeshLogger.log("🚫 Message Send Failed, not properly connected to \(lastConnectedPeripheral)") }
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
@ -845,7 +846,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 {
@ -859,8 +860,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 = "Primary - Broadcast"
bcu.hwModel = "UNSET"
bcu.num = Int64(broadcastNodeNum)
bcu.userId = "BROADCASTNODE"
@ -887,12 +888,17 @@ 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 {
try context!.save()
print("Saved a new sent message from \(connectedPeripheral.num)")
print("💾 Saved a new sent message from \(newMessage.fromUser?.longName! ?? "Unknown")")
if meshLoggingEnabled { MeshLogger.log("💾 Saved a new sent message from \(connectedPeripheral.num)") }
success = true
nextSentMessageId+=1
@ -901,7 +907,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

@ -0,0 +1,126 @@
//
// Contacts.swift
// MeshtasticClient
//
// Created by Garth Vander Houwen on 12/21/21.
//
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 {
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)
}
.padding([.leading, .trailing])
VStack {
HStack {
VStack {
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
}
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)
.foregroundColor(Color.gray)
.frame(maxWidth: .infinity, alignment: .leading)
}
}.padding(.top, 15)
}
} else {
HStack {
VStack {
CircleText(text: user.shortName ?? "???", color: Color.blue)
}
.padding(.trailing)
VStack {
HStack{
VStack {
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
}
VStack {
Text(" ")
}
.frame(maxWidth: .infinity, alignment: .trailing)
}
.listRowSeparator(.hidden).frame(height: 5)
}
}.padding()
}
//NavigationLink(note.title, destination: NoteEditor(id: note.id))
}
.navigationTitle("Contacts")
}
.listStyle(PlainListStyle())
}
}
struct Contacts_Previews: PreviewProvider {
static var previews: some View {
Contacts()
}
}

View file

@ -49,7 +49,6 @@ struct Messages: View {
HStack(alignment: .top) {
let currentUser: Bool = (bleManager.connectedPeripheral == nil) ? false : ((bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.num == message.fromUser?.num) ? true : false )
//let currentUser: (Bool = message.fromUser == nil : false : (message.fromUser != nil && bleManager.connectedPeripheral.num == message.fromUser!.num : true)
CircleText(text: (message.fromUser?.shortName ?? "???"), color: currentUser ? .accentColor : Color(.darkGray)).padding(.all, 5)
.gesture(LongPressGesture(minimumDuration: 2)

View file

@ -0,0 +1,20 @@
//
// UserMessageList.swift
// MeshtasticClient
//
// Created by Garth Vander Houwen on 12/24/21.
//
import SwiftUI
struct UserMessageList: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
struct UserMessageList_Previews: PreviewProvider {
static var previews: some View {
UserMessageList()
}
}

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")