myInfo data for both peripheral and node info model fixed data loading and cleaned up models

This commit is contained in:
Garth Vander Houwen 2021-09-23 20:10:53 -07:00
parent c1200569fb
commit ebf243f203
9 changed files with 127 additions and 61 deletions

View file

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
DD47E3CC26F0E51D00029299 /* NodeDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3CB26F0E51D00029299 /* NodeDetail.swift */; };
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3CD26F103C600029299 /* NodeList.swift */; };
DD47E3D026F1073F00029299 /* NodeRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3CF26F1073F00029299 /* NodeRow.swift */; };
@ -65,6 +66,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
DD47E3CB26F0E51D00029299 /* 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>"; };
DD47E3CF26F1073F00029299 /* NodeRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeRow.swift; sourceTree = "<group>"; };
@ -265,6 +267,7 @@
DD836AEE26F85D8D00ABCC23 /* NodeInfoModel.swift */,
DD836AF026F8613500ABCC23 /* Color.swift */,
DDF924CC26FCC97E009FE055 /* PacketModel.swift */,
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */,
);
path = Model;
sourceTree = "<group>";
@ -465,6 +468,7 @@
DDF924CD26FCC97E009FE055 /* PacketModel.swift in Sources */,
DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */,
DD47E3DF26F39D9F00029299 /* MyInfoModel.swift in Sources */,
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
DD47E3D026F1073F00029299 /* NodeRow.swift in Sources */,
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,

View file

@ -3,20 +3,6 @@ import CoreData
import CoreBluetooth
import SwiftUI
final class Peripheral: Identifiable, ObservableObject {
@Published var id: String
@Published var index: Int
@Published var name: String
@Published var rssi: Int
init(id: String, index: Int, name: String, rssi: Int) {
self.id = id
self.index = index
self.name = name
self.rssi = rssi
}
}
//---------------------------------------------------------------------------------------
// Meshtastic BLE Device Manager
//---------------------------------------------------------------------------------------
@ -27,7 +13,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
private var centralManager: CBCentralManager!
@Published var connectedPeripheral: CBPeripheral!
@Published var peripheralArray = [CBPeripheral]()
@Published var connectedNodeInfo: MyInfoModel!
@Published var connectedNodeInfo: Peripheral!
@Published var connectedNode: NodeInfoModel!
//private var rssiArray = [NSNumber]()
private var timer = Timer()
@Published var isSwitchedOn = false
@ -89,6 +76,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
//---------------------------------------------------------------------------------------
func connectToDevice(id: String) {
connectedPeripheral = peripheralArray.filter({ $0.identifier.uuidString == id }).first
connectedNodeInfo = Peripheral(id: connectedPeripheral.identifier.uuidString, name: connectedPeripheral.name ?? "Unknown", rssi: 0, myInfo: nil)
self.centralManager?.connect(connectedPeripheral!)
}
@ -148,7 +136,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
}
}
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, index: peripherals.count, name: peripheralName, rssi: RSSI.intValue)
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue, myInfo: nil)
//print(newPeripheral)
peripherals.append(newPeripheral)
}
@ -260,11 +248,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
if decodedInfo.myInfo.myNodeNum != 0
{
meshData.load()
print("Save a myInfo")
do {
print(try decodedInfo.myInfo.jsonString())
connectedNodeInfo = MyInfoModel(
// Create a MyInfoModel
let myInfoModel = MyInfoModel(
myNodeNum: decodedInfo.myInfo.myNodeNum,
hasGps: decodedInfo.myInfo.hasGps_p,
numBands: decodedInfo.myInfo.numBands,
@ -273,7 +262,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
rebootCount: decodedInfo.myInfo.rebootCount,
messageTimeoutMsec: decodedInfo.myInfo.messageTimeoutMsec,
minAppVersion: decodedInfo.myInfo.minAppVersion)
// Save it to the connected nodeInfo
connectedNodeInfo.myInfo = myInfoModel
// Save it to the connected node
connectedNode = meshData.nodes.first(where: {$0.id == decodedInfo.myInfo.myNodeNum})
if connectedNode != nil {
connectedNode.myInfo = myInfoModel
let nodeIndex = meshData.nodes.firstIndex(where: { $0.id == decodedInfo.myInfo.myNodeNum })
meshData.nodes.remove(at: nodeIndex!)
meshData.nodes.append(connectedNode)
}
meshData.save()
} catch {
fatalError("Failed to decode json")
}

View file

@ -8,7 +8,7 @@ struct NodeInfoModel: Identifiable, Codable {
var id: UInt32
var num: UInt32
var myInfo: MyInfoModel?
var user: User
struct User: Identifiable, Codable {
var id: String

View file

@ -0,0 +1,16 @@
import Foundation
final class Peripheral: Identifiable {
var id: String
var name: String
var rssi: Int
var myInfo: MyInfoModel?
init(id: String, name: String, rssi: Int, myInfo: MyInfoModel?) {
self.id = id
self.name = name
self.rssi = rssi
self.myInfo = myInfo
}
}

View file

@ -27,12 +27,28 @@ struct Connect: View {
List {
Section(header: Text("Connected Device").font(.title)) {
if(bleManager.connectedPeripheral != nil){
HStack{
HStack {
Image(systemName: "antenna.radiowaves.left.and.right")
.symbolRenderingMode(.hierarchical)
.imageScale(.large).foregroundColor(.green)
.padding(.trailing)
Text((bleManager.connectedPeripheral.name != nil) ? bleManager.connectedPeripheral.name! : "Unknown").font(.title2)
if bleManager.connectedNodeInfo.myInfo != nil {
VStack (alignment: .leading) {
if bleManager.connectedNode != nil {
Text(bleManager.connectedNode.user.longName).font(.title2)
}
else {
Text(String(bleManager.connectedNodeInfo.myInfo?.myNodeNum ?? 0)).font(.title2)
}
Text("FW Version: ").font(.caption)+Text(bleManager.connectedNodeInfo.myInfo?.firmwareVersion ?? "(null)").font(.caption).foregroundColor(Color.gray)
}
}
else {
Text((bleManager.connectedPeripheral.name != nil) ? bleManager.connectedPeripheral.name! : "Unknown").font(.title2)
}
}
.padding()
.swipeActions {

View file

@ -54,22 +54,10 @@ struct NodeDetail: View {
}
ScrollView {
HStack {
Image(node.user.hwModel)
.resizable()
.frame(width:70, height: 70)
.cornerRadius(5)
Text("Model: " + String(node.user.hwModel))
.font(.title)
}
.padding()
Divider()
HStack {
VStack(alignment: .center) {
Text("AKA").font(.title3)
Text("AKA").font(.title2)
CircleText(text: node.user.shortName, color: Color.blue)
.offset(y:10)
}
@ -78,25 +66,37 @@ struct NodeDetail: View {
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title2)
.font(.title)
.foregroundColor(.blue)
.symbolRenderingMode(.hierarchical)
Text("SNR").font(.title3)
Text("SNR").font(.title2)
Text(String(node.snr ?? 0))
.font(.title3)
.font(.title2)
.foregroundColor(.gray)
}
Divider()
VStack(alignment: .center) {
BatteryIcon(batteryLevel: node.position.batteryLevel, font: .title, color: Color.blue)
Text("Battery").font(.title3)
Text("Battery").font(.title2)
Text(String(node.position.batteryLevel!) + "%")
.font(.title3)
.font(.title2)
.foregroundColor(.gray)
.symbolRenderingMode(.hierarchical)
}
}.padding(4)
Divider()
HStack {
Image(node.user.hwModel)
.resizable()
.frame(width:60, height: 60)
.cornerRadius(5)
Text("Model: " + String(node.user.hwModel))
.font(.title3)
}
.padding()
Divider()
HStack{
Image(systemName: "clock").font(.title2).foregroundColor(.blue)

View file

@ -6,7 +6,7 @@
//
// Abstract:
// A view showing a list of devices that have been seen on the mesh network
// A view showing a list of devices that have been seen on the mesh network from the perspective of the connected device.
import SwiftUI
@ -26,30 +26,57 @@ struct NodeList: View {
NavigationView {
List {
Toggle(isOn: $showLocationOnly) {
Text("Nodes with location only")
if meshData.nodes.count == 0 {
Text("Scan for Radios").font(.largeTitle).listRowSeparator(.hidden)
Text("No LoRa Mesh Nodes Found").font(.title2).listRowSeparator(.hidden)
Text("Go to the bluetooth section in the bottom right menu and click the Start Scanning button to scan for nearby radios and find your Meshtastic device. Make sure your device is powered on and near your phone or tablet.")
.font(.body)
.listRowSeparator(.hidden)
Text("Once the device shows under Available Devices touch the device you want to connect to and it will pull node information over BLE and populate the node list and mesh map in the Meshtastic app.")
.listRowSeparator(.hidden)
Text("Views with bluetooth functionality will show an indicator in the upper right hand corner show if bluetooth is on, and if a device is connected.")
.listRowSeparator(.hidden)
Spacer().listRowSeparator(.hidden)
//Button(action: {}) {
// Text("Get Started")
// .font(.title)
// .frame(maxWidth: 300)
//}
//.buttonStyle(.borderedProminent)
//.buttonBorderShape(.automatic)
//.controlSize(.large)
}
ForEach(filteredDevices.sorted(by: { $0.lastHeard > $1.lastHeard })) { node in
NavigationLink(destination: NodeDetail(node: node)) {
NodeRow(node: node, index : 0)
else {
Toggle(isOn: $showLocationOnly) {
Text("Nodes with location only")
}
.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")
}
ForEach(filteredDevices.sorted(by: { $0.lastHeard > $1.lastHeard })) { node in
NavigationLink(destination: NodeDetail(node: node)) {
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)
}
.tint(.red)
}
}
}
.navigationTitle("All Nodes")
}
.ignoresSafeArea(.all, edges: [.leading, .trailing])
.onAppear{
meshData.load()
}
}
}

View file

@ -33,7 +33,7 @@ struct NodeMap: View {
let currentCoordinatePosition = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
let regionBinding = Binding<MKCoordinateRegion>(
get: {
MKCoordinateRegion(center: currentCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.09, longitudeDelta: 0.09))
MKCoordinateRegion(center: currentCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.0359, longitudeDelta: 0.0359))
},
set: { _ in }
)
@ -52,11 +52,15 @@ struct NodeMap: View {
CircleText(text: location.user.shortName, color: Color.blue)
}
)
}.frame(maxHeight:.infinity)
}
.frame(maxHeight:.infinity)
.ignoresSafeArea(.all, edges: [.leading, .trailing])
}
.navigationTitle("Mesh Map")
.navigationBarTitleDisplayMode(.inline)
}.navigationViewStyle(StackNavigationViewStyle())
}
.navigationViewStyle(StackNavigationViewStyle())
}
}

View file

@ -19,7 +19,6 @@ struct NodeRow: View {
Text(lastHeard, style: .relative).font(.caption).foregroundColor(.gray)
}
}.padding([.leading, .top, .bottom])
}
}