diff --git a/Meshtastic Client.xcodeproj/project.pbxproj b/Meshtastic Client.xcodeproj/project.pbxproj index 7cf01a35..93a2b806 100644 --- a/Meshtastic Client.xcodeproj/project.pbxproj +++ b/Meshtastic Client.xcodeproj/project.pbxproj @@ -43,8 +43,8 @@ DDC2E19126CE26290042C5E4 /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E19026CE26290042C5E4 /* Messages.swift */; }; DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */; }; DDF924C626FA2375009FE055 /* MessageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C526FA2375009FE055 /* MessageModel.swift */; }; - DDF924C826FA5BAD009FE055 /* TabBarIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C726FA5BAD009FE055 /* TabBarIcon.swift */; }; DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C926FBB953009FE055 /* ConnectedDevice.swift */; }; + DDF924CD26FCC97E009FE055 /* PacketModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924CC26FCC97E009FE055 /* PacketModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -107,8 +107,9 @@ DDC2E19026CE26290042C5E4 /* Messages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Messages.swift; sourceTree = ""; }; DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHelper.swift; sourceTree = ""; }; DDF924C526FA2375009FE055 /* MessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageModel.swift; sourceTree = ""; }; - DDF924C726FA5BAD009FE055 /* TabBarIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarIcon.swift; sourceTree = ""; }; DDF924C926FBB953009FE055 /* ConnectedDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectedDevice.swift; sourceTree = ""; }; + DDF924CB26FCC916009FE055 /* packets.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = packets.json; sourceTree = ""; }; + DDF924CC26FCC97E009FE055 /* PacketModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -263,6 +264,7 @@ DD836AEC26F858F900ABCC23 /* MeshData.swift */, DD836AEE26F85D8D00ABCC23 /* NodeInfoModel.swift */, DD836AF026F8613500ABCC23 /* Color.swift */, + DDF924CC26FCC97E009FE055 /* PacketModel.swift */, ); path = Model; sourceTree = ""; @@ -270,6 +272,7 @@ DDC2E18926CE24F70042C5E4 /* Resources */ = { isa = PBXGroup; children = ( + DDF924CB26FCC916009FE055 /* packets.json */, ); path = Resources; sourceTree = ""; @@ -290,7 +293,6 @@ DD47E3D526F17ED900029299 /* CircleText.swift */, DD47E3D826F3093800029299 /* MessageBubble.swift */, DD90860B26F684AF00DC5189 /* BatteryIcon.swift */, - DDF924C726FA5BAD009FE055 /* TabBarIcon.swift */, DDF924C926FBB953009FE055 /* ConnectedDevice.swift */, ); path = Helpers; @@ -442,7 +444,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DDF924C826FA5BAD009FE055 /* TabBarIcon.swift in Sources */, DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */, DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */, DD47E3CC26F0E51D00029299 /* NodeDetail.swift in Sources */, @@ -461,6 +462,7 @@ DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */, DDAF8C6226ED0A230058C060 /* mqtt.pb.swift in Sources */, DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */, + DDF924CD26FCC97E009FE055 /* PacketModel.swift in Sources */, DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */, DD47E3DF26F39D9F00029299 /* MyInfoModel.swift in Sources */, DD47E3CE26F103C600029299 /* NodeList.swift in Sources */, @@ -643,7 +645,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.093; + MARKETING_VERSION = 1.11; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = NO; @@ -669,7 +671,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.093; + MARKETING_VERSION = 1.11; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = NO; diff --git a/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-1.png b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-1.png new file mode 100644 index 00000000..b80e4b0c Binary files /dev/null and b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-1.png differ diff --git a/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-2.png b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-2.png new file mode 100644 index 00000000..b80e4b0c Binary files /dev/null and b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6-2.png differ diff --git a/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6.png b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6.png new file mode 100644 index 00000000..b80e4b0c Binary files /dev/null and b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/655DCEC0-309D-430A-AF50-2453B6ADB1F6.png differ diff --git a/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/Contents.json b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/Contents.json new file mode 100644 index 00000000..f321d22c --- /dev/null +++ b/MeshtasticClient/Assets.xcassets/HELTECV20.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "655DCEC0-309D-430A-AF50-2453B6ADB1F6.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "655DCEC0-309D-430A-AF50-2453B6ADB1F6-1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "655DCEC0-309D-430A-AF50-2453B6ADB1F6-2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MeshtasticClient/Assets.xcassets/TLORAV2.imageset/Contents.json b/MeshtasticClient/Assets.xcassets/TLORAV2.imageset/Contents.json new file mode 100644 index 00000000..a19a5492 --- /dev/null +++ b/MeshtasticClient/Assets.xcassets/TLORAV2.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MeshtasticClient/Assets.xcassets/TLORAV211p6.imageset/Contents.json b/MeshtasticClient/Assets.xcassets/TLORAV211p6.imageset/Contents.json new file mode 100644 index 00000000..a19a5492 --- /dev/null +++ b/MeshtasticClient/Assets.xcassets/TLORAV211p6.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MeshtasticClient/Assets.xcassets/UNSET.imageset/Contents.json b/MeshtasticClient/Assets.xcassets/UNSET.imageset/Contents.json new file mode 100644 index 00000000..a19a5492 --- /dev/null +++ b/MeshtasticClient/Assets.xcassets/UNSET.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MeshtasticClient/Helpers/BLEManager.swift b/MeshtasticClient/Helpers/BLEManager.swift index 7a41aa6f..c68b96c8 100644 --- a/MeshtasticClient/Helpers/BLEManager.swift +++ b/MeshtasticClient/Helpers/BLEManager.swift @@ -27,6 +27,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph private var centralManager: CBCentralManager! @Published var connectedPeripheral: CBPeripheral! @Published var peripheralArray = [CBPeripheral]() + @Published var connectedNodeInfo: MyInfoModel! //private var rssiArray = [NSNumber]() private var timer = Timer() @Published var isSwitchedOn = false @@ -100,6 +101,28 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } } + + //--------------------------------------------------------------------------------------- + // Disconnect Device function + //--------------------------------------------------------------------------------------- + public func setOwner(myUser: User) + { + var toRadio: ToRadio! + toRadio = ToRadio() +//toRadio.setOwner = myUser + + let binaryData: Data = try! toRadio.serializedData() + if (self.connectedPeripheral.state == CBPeripheralState.connected) + { + connectedPeripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse) + //MasterViewController.shared.DebugPrint2View(text: "Owner set to device" + "\n\r") + } + else + { + connectToDevice(id: self.connectedPeripheral.identifier.uuidString) + } + } + //--------------------------------------------------------------------------------------- // Discover Peripheral Event //--------------------------------------------------------------------------------------- @@ -241,6 +264,15 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph print("Save a myInfo") do { print(try decodedInfo.myInfo.jsonString()) + connectedNodeInfo = MyInfoModel( + myNodeNum: decodedInfo.myInfo.myNodeNum, + hasGps: decodedInfo.myInfo.hasGps_p, + numBands: decodedInfo.myInfo.numBands, + maxChannels: decodedInfo.myInfo.maxChannels, + firmwareVersion: decodedInfo.myInfo.firmwareVersion, + rebootCount: decodedInfo.myInfo.rebootCount, + messageTimeoutMsec: decodedInfo.myInfo.messageTimeoutMsec, + minAppVersion: decodedInfo.myInfo.minAppVersion) } catch { fatalError("Failed to decode json") @@ -293,6 +325,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph print("Save a packet") do { print(try decodedInfo.packet.jsonString()) + if decodedInfo.packet.decoded.portnum == PortNum.textMessageApp { + print(try decodedInfo.packet.jsonString()) + } + } catch { fatalError("Failed to decode json") } diff --git a/MeshtasticClient/Model/MessageModel.swift b/MeshtasticClient/Model/MessageModel.swift index d6b61bb5..a006fc43 100644 --- a/MeshtasticClient/Model/MessageModel.swift +++ b/MeshtasticClient/Model/MessageModel.swift @@ -6,7 +6,7 @@ // import Foundation -struct ChatMessage : Identifiable +struct MessageModel : Identifiable { let id: UUID var messageId: UInt32 diff --git a/MeshtasticClient/Model/MyInfoModel.swift b/MeshtasticClient/Model/MyInfoModel.swift index ecd52423..52d83f5a 100644 --- a/MeshtasticClient/Model/MyInfoModel.swift +++ b/MeshtasticClient/Model/MyInfoModel.swift @@ -9,7 +9,7 @@ import Foundation struct MyInfoModel: Identifiable, Codable { - let id: UUID + let id: UInt32 var myNodeNum: UInt32 var hasGps: Bool var numBands: UInt32 @@ -19,9 +19,9 @@ struct MyInfoModel: Identifiable, Codable { var messageTimeoutMsec: UInt32 var minAppVersion: UInt32 - init(id: UUID = UUID(), myNodeNum: UInt32, hasGps: Bool, numBands: UInt32, maxChannels: UInt32, firmwareVersion: String, rebootCount: UInt32, messageTimeoutMsec: UInt32, minAppVersion: UInt32) { + init(myNodeNum: UInt32, hasGps: Bool, numBands: UInt32, maxChannels: UInt32, firmwareVersion: String, rebootCount: UInt32, messageTimeoutMsec: UInt32, minAppVersion: UInt32) { - self.id = id + self.id = myNodeNum self.myNodeNum = myNodeNum self.hasGps = hasGps self.numBands = numBands diff --git a/MeshtasticClient/Model/PacketModel.swift b/MeshtasticClient/Model/PacketModel.swift new file mode 100644 index 00000000..55bff11a --- /dev/null +++ b/MeshtasticClient/Model/PacketModel.swift @@ -0,0 +1,8 @@ +// +// PacketModel.swift +// MeshtasticClient +// +// Created by Garth Vander Houwen on 9/23/21. +// + +import Foundation diff --git a/MeshtasticClient/Resources/packets.json b/MeshtasticClient/Resources/packets.json new file mode 100644 index 00000000..a4a6da5a --- /dev/null +++ b/MeshtasticClient/Resources/packets.json @@ -0,0 +1,14 @@ +[ + { + "from":4064715620, + "to":4294967295, + "decoded":{ + "portnum":"TEXT_MESSAGE_APP", + "payload":"YmFsbHM=" + + }, + "id":3773493287, + "rxTime":1632407404, + "rxSnr":10.75, + "hopLimit":3} +] diff --git a/MeshtasticClient/Views/Helpers/TabBarIcon.swift b/MeshtasticClient/Views/Helpers/TabBarIcon.swift deleted file mode 100644 index 58a9770e..00000000 --- a/MeshtasticClient/Views/Helpers/TabBarIcon.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Foundation -import SwiftUI - -struct TabBarIcon: View { - - let width, height: CGFloat - let systemIconName, tabName: String - - - var body: some View { - VStack { - Image(systemName: systemIconName) - .symbolRenderingMode(.hierarchical) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: width, height: height) - .padding(.top, 10) - Text(tabName) - .font(.footnote) - Spacer() - } - } - } diff --git a/MeshtasticClient/Views/Nodes/NodeDetail.swift b/MeshtasticClient/Views/Nodes/NodeDetail.swift index c9f7031a..9a466824 100644 --- a/MeshtasticClient/Views/Nodes/NodeDetail.swift +++ b/MeshtasticClient/Views/Nodes/NodeDetail.swift @@ -47,7 +47,7 @@ struct NodeDetail: View { } else { - Image(node.user.hwModel.lowercased()) + Image(node.user.hwModel) .resizable() .aspectRatio(contentMode: .fit) .frame(width: bounds.size.width, height: bounds.size.height / 2) @@ -56,7 +56,7 @@ struct NodeDetail: View { HStack { - Image(node.user.hwModel.lowercased()) + Image(node.user.hwModel) .resizable() .frame(width:70, height: 70) .cornerRadius(5) diff --git a/MeshtasticClient/Views/Nodes/NodeList.swift b/MeshtasticClient/Views/Nodes/NodeList.swift index e62459c0..a31d6bf7 100644 --- a/MeshtasticClient/Views/Nodes/NodeList.swift +++ b/MeshtasticClient/Views/Nodes/NodeList.swift @@ -34,8 +34,20 @@ struct NodeList: View { NodeRow(node: node, index : 0) } + .swipeActions { + Button { + let nodeIndex = meshData.nodes.firstIndex(where: { $0.id == node.id }) + meshData.nodes.remove(at: nodeIndex!) + meshData.save() + } label: { + VStack { + Label("Delete from app", systemImage: "trash") + } + } + .tint(.red) + } } - } + } .navigationTitle("All Nodes") } } diff --git a/MeshtasticClient/Views/Nodes/NodeRow.swift b/MeshtasticClient/Views/Nodes/NodeRow.swift index 831ad79b..2cdfccbe 100644 --- a/MeshtasticClient/Views/Nodes/NodeRow.swift +++ b/MeshtasticClient/Views/Nodes/NodeRow.swift @@ -19,6 +19,7 @@ struct NodeRow: View { Text(lastHeard, style: .relative).font(.caption).foregroundColor(.gray) } }.padding([.leading, .top, .bottom]) + } }