mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Rebuild nodes page with data from device, improve layout consistency
This commit is contained in:
parent
a27e8b29fa
commit
ccf5bf1610
18 changed files with 647 additions and 227 deletions
|
|
@ -7,7 +7,12 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
DD8E565A26EE85E3002CD952 /* MeshtasticClient.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DD8E565826EE85E3002CD952 /* MeshtasticClient.xcdatamodeld */; };
|
||||
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 */; };
|
||||
DD47E3D226F1210600029299 /* HelperFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3D126F1210600029299 /* HelperFunctions.swift */; };
|
||||
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3D526F17ED900029299 /* CircleText.swift */; };
|
||||
DD7AA3F326F05C120077AF76 /* NodeInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7AA3F226F05C120077AF76 /* NodeInfoModel.swift */; };
|
||||
DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5226EB1DF10058C060 /* BLEManager.swift */; };
|
||||
DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */; };
|
||||
DDAF8C5B26ED08D30058C060 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = DDAF8C5A26ED08D30058C060 /* SwiftProtobuf */; };
|
||||
|
|
@ -59,7 +64,13 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
DD8E565926EE85E3002CD952 /* MeshtasticClient.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticClient.xcdatamodel; 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>"; };
|
||||
DD47E3D126F1210600029299 /* HelperFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperFunctions.swift; sourceTree = "<group>"; };
|
||||
DD47E3D526F17ED900029299 /* CircleText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleText.swift; sourceTree = "<group>"; };
|
||||
DD7AA3F226F05C120077AF76 /* NodeInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoModel.swift; sourceTree = "<group>"; };
|
||||
DD7AA3F426F05D660077AF76 /* nodeInfoModel.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = nodeInfoModel.json; sourceTree = "<group>"; };
|
||||
DDAF8C5226EB1DF10058C060 /* BLEManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManager.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mesh.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5C26ED09490058C060 /* portnums.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = portnums.pb.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -125,6 +136,16 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
DD47E3CA26F0E50300029299 /* Nodes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD47E3CB26F0E51D00029299 /* NodeDetail.swift */,
|
||||
DD47E3CD26F103C600029299 /* NodeList.swift */,
|
||||
DD47E3CF26F1073F00029299 /* NodeRow.swift */,
|
||||
);
|
||||
path = Nodes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDAF8C5626ED07740058C060 /* Protobufs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -206,6 +227,7 @@
|
|||
DDC2E18726CE24E40042C5E4 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD47E3CA26F0E50300029299 /* Nodes */,
|
||||
DDC2E18C26CE25B00042C5E4 /* Devices */,
|
||||
DDC2E18B26CE25A70042C5E4 /* Messages */,
|
||||
DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */,
|
||||
|
|
@ -217,10 +239,10 @@
|
|||
DDC2E18826CE24EE0042C5E4 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD8E565826EE85E3002CD952 /* MeshtasticClient.xcdatamodeld */,
|
||||
DDC2E19C26CE27580042C5E4 /* ModelData.swift */,
|
||||
DDC2E19E26CE27630042C5E4 /* Device.swift */,
|
||||
DDAF8C6F26ED1DD20058C060 /* Device2.swift */,
|
||||
DD7AA3F226F05C120077AF76 /* NodeInfoModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -231,6 +253,7 @@
|
|||
DDC2E18A26CE25690042C5E4 /* deviceData.json */,
|
||||
DDC2E1AA26DD89EC0042C5E4 /* packets.json */,
|
||||
DDAF8C7126ED2AD80058C060 /* nodeInfo.json */,
|
||||
DD7AA3F426F05D660077AF76 /* nodeInfoModel.json */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -259,6 +282,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DDC2E19A26CE27150042C5E4 /* CircleImage.swift */,
|
||||
DD47E3D526F17ED900029299 /* CircleText.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -269,6 +293,7 @@
|
|||
DDAF8C5226EB1DF10058C060 /* BLEManager.swift */,
|
||||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */,
|
||||
DDAF8C6D26ED19040058C060 /* Extensions.swift */,
|
||||
DD47E3D126F1210600029299 /* HelperFunctions.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -411,9 +436,12 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */,
|
||||
DD47E3CC26F0E51D00029299 /* NodeDetail.swift in Sources */,
|
||||
DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */,
|
||||
DDAF8C7026ED1DD20058C060 /* Device2.swift in Sources */,
|
||||
DD7AA3F326F05C120077AF76 /* NodeInfoModel.swift in Sources */,
|
||||
DDC2E19F26CE27630042C5E4 /* Device.swift in Sources */,
|
||||
DD47E3D226F1210600029299 /* HelperFunctions.swift in Sources */,
|
||||
DDC2E19926CE26940042C5E4 /* DeviceMap.swift in Sources */,
|
||||
DDC2E19526CE26760042C5E4 /* DeviceDetail.swift in Sources */,
|
||||
DDAF8C5F26ED09B50058C060 /* radioconfig.pb.swift in Sources */,
|
||||
|
|
@ -425,9 +453,11 @@
|
|||
DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */,
|
||||
DDAF8C6226ED0A230058C060 /* mqtt.pb.swift in Sources */,
|
||||
DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */,
|
||||
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
|
||||
DD47E3D026F1073F00029299 /* NodeRow.swift in Sources */,
|
||||
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,
|
||||
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */,
|
||||
DDAF8C6326ED0A230058C060 /* admin.pb.swift in Sources */,
|
||||
DD8E565A26EE85E3002CD952 /* MeshtasticClient.xcdatamodeld in Sources */,
|
||||
DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */,
|
||||
DDC2E19326CE266B0042C5E4 /* DeviceHome.swift in Sources */,
|
||||
DDC2E19B26CE27150042C5E4 /* CircleImage.swift in Sources */,
|
||||
|
|
@ -773,19 +803,6 @@
|
|||
productName = SwiftProtobuf;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
/* Begin XCVersionGroup section */
|
||||
DD8E565826EE85E3002CD952 /* MeshtasticClient.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
DD8E565926EE85E3002CD952 /* MeshtasticClient.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD8E565926EE85E3002CD952 /* MeshtasticClient.xcdatamodel */;
|
||||
path = MeshtasticClient.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
versionGroupType = wrapper.xcdatamodel;
|
||||
};
|
||||
/* End XCVersionGroup section */
|
||||
};
|
||||
rootObject = DDC2E14C26CE248E0042C5E4 /* Project object */;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
import CoreBluetooth
|
||||
import SwiftUI
|
||||
|
||||
struct Peripheral: Identifiable {
|
||||
let id: String
|
||||
|
|
@ -20,7 +21,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
@Published var peripheralArray = [CBPeripheral]()
|
||||
private var rssiArray = [NSNumber]()
|
||||
private var timer = Timer()
|
||||
|
||||
@Published var isSwitchedOn = false
|
||||
@Published var peripherals = [Peripheral]()
|
||||
|
||||
|
|
@ -230,6 +230,17 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
print("Save a myInfo")
|
||||
do {
|
||||
print(try decodedInfo.myInfo.jsonString())
|
||||
// let node = MyInfoEntity(context: persistentContainer.viewContext)
|
||||
// node.myNodeNum = Int64(decodedInfo.myInfo.myNodeNum)
|
||||
|
||||
// node.num = Int(decodedInfo.myInfo.myNodeNum)
|
||||
// node.user?.hwModel = decodedInfo.myInfo.hwModelDeprecated
|
||||
//node.lastHeard
|
||||
// node.snr
|
||||
|
||||
// node.user?.shortName decodedInfo.myInfo.
|
||||
|
||||
// try persistentContainer.viewContext.save()
|
||||
} catch {
|
||||
fatalError("Failed to decode json")
|
||||
}
|
||||
|
|
@ -239,7 +250,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
{
|
||||
print("Save a nodeInfo")
|
||||
do {
|
||||
let node =
|
||||
print(try decodedInfo.nodeInfo.jsonString())
|
||||
} catch {
|
||||
fatalError("Failed to decode json")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
extension Data
|
||||
{
|
||||
|
|
@ -8,6 +9,13 @@ extension Data
|
|||
}
|
||||
}
|
||||
|
||||
extension Date
|
||||
{
|
||||
static var currentTimeStamp: Int64
|
||||
{
|
||||
return Int64(Date().timeIntervalSince1970 * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
extension String
|
||||
{
|
||||
|
|
@ -36,11 +44,40 @@ extension String
|
|||
|
||||
}
|
||||
|
||||
typealias NodeColor = Int
|
||||
|
||||
extension Date
|
||||
{
|
||||
static var currentTimeStamp: Int64
|
||||
{
|
||||
return Int64(Date().timeIntervalSince1970 * 1000)
|
||||
extension NodeColor {
|
||||
// a color to represent an individual meshtastic device
|
||||
var color: Color {
|
||||
switch self {
|
||||
case 0:
|
||||
return Color(.red)
|
||||
case 1:
|
||||
return Color(.blue)
|
||||
case 2:
|
||||
return Color(.yellow)
|
||||
case 3:
|
||||
return Color(.green)
|
||||
case 4:
|
||||
return Color(.purple)
|
||||
case 5:
|
||||
return Color(.systemPink)
|
||||
case 6:
|
||||
return Color(.systemTeal)
|
||||
case 7:
|
||||
return Color(.black)
|
||||
case 8:
|
||||
return Color(.gray)
|
||||
case 9:
|
||||
return Color(.brown)
|
||||
case 10:
|
||||
return Color(.magenta)
|
||||
case 11:
|
||||
return Color(.orange)
|
||||
case 12:
|
||||
return Color(.cyan)
|
||||
default:
|
||||
return Color(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
MeshtasticClient/Helpers/HelperFunctions.swift
Normal file
11
MeshtasticClient/Helpers/HelperFunctions.swift
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// HelperFunctions.swift
|
||||
// MeshtasticClient
|
||||
//
|
||||
// Created by Garth Vander Houwen on 9/14/21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
|
|
@ -9,6 +9,8 @@ import Combine
|
|||
final class ModelData: ObservableObject {
|
||||
@Published var devices: [Device] = load("deviceData.json")
|
||||
|
||||
@Published var nodes: [NodeInfoModel] = load("packets.json")
|
||||
|
||||
var nearby: [Device] {
|
||||
devices
|
||||
}
|
||||
|
|
|
|||
37
MeshtasticClient/Model/NodeInfoModel.swift
Normal file
37
MeshtasticClient/Model/NodeInfoModel.swift
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// NodeInfo.swift
|
||||
// MeshtasticClient
|
||||
//
|
||||
// Created by Garth Vander Houwen on 9/13/21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CoreLocation
|
||||
|
||||
struct NodeInfoModel: Hashable, Codable, Identifiable {
|
||||
|
||||
let id = UUID()
|
||||
var num: UInt32
|
||||
|
||||
var user: User
|
||||
struct User: Hashable, Codable, Identifiable {
|
||||
var id: String
|
||||
var longName: String
|
||||
var shortName: String
|
||||
var macaddr: String
|
||||
var hwModel: String
|
||||
}
|
||||
|
||||
var position: Position
|
||||
struct Position: Hashable, Codable {
|
||||
var latitudeI: Int32?
|
||||
var longitudeI: Int32?
|
||||
var altitude: Int32?
|
||||
var batteryLevel: Int32?
|
||||
var time: Int32?
|
||||
}
|
||||
|
||||
var lastHeard: Double
|
||||
var snr: Double?
|
||||
}
|
||||
|
|
@ -1,38 +1,43 @@
|
|||
[{
|
||||
"nodeInfo": {
|
||||
"num":3186677820,
|
||||
[
|
||||
{
|
||||
"num":2792101487,
|
||||
"user":{
|
||||
"id":"!bdf0d83c",
|
||||
"longName":"Garth Vander Houwen",
|
||||
"shortName":"GVH",
|
||||
"macaddr":"fJ698Ng8",
|
||||
"hwModel":"TBEAM"
|
||||
"id":"!a66c166f",
|
||||
"longName":"RAK Solar 2",
|
||||
"shortName":"RS2",
|
||||
"macaddr":"8eambBZv",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476040257,
|
||||
"longitudeI":-1221545412,
|
||||
"altitude":11,
|
||||
"batteryLevel":100,
|
||||
"time":1631384279
|
||||
},
|
||||
"lastHeard":1631384279
|
||||
"batteryLevel":68},
|
||||
"lastHeard":1631593661
|
||||
}
|
||||
},
|
||||
{
|
||||
"nodeInfo":{
|
||||
"num":2792101487,
|
||||
"user":{
|
||||
"id":"!a66c166f",
|
||||
"longName":"RAK Solar 2",
|
||||
"shortName":"RS2",
|
||||
"macaddr":"8eambBZv",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"batteryLevel":88,
|
||||
"time":1631297585
|
||||
},
|
||||
"lastHeard":1631383493,
|
||||
"snr":12.0
|
||||
}
|
||||
}
|
||||
}]
|
||||
"num":1000569662,
|
||||
"user":{
|
||||
"id":"!3ba37b3e",
|
||||
"longName":"RAK Solar 1",
|
||||
"shortName":"RS1",
|
||||
"macaddr":"1Kc7o3s+",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476021390,
|
||||
"longitudeI":-1221532609,
|
||||
"altitude":71,
|
||||
"batteryLevel":70,
|
||||
"time":1629314497
|
||||
},
|
||||
"lastHeard":1629392801,
|
||||
"snr":5.25
|
||||
},
|
||||
{"num":1133445808,"user":{"id":"!438f02b0","longName":"RAK DEV NODE","shortName":"RDN","macaddr":"92VDjwKw","hwModel":"RAK4631"},"position":{"latitudeI":476022071,"longitudeI":-1221533607,"altitude":91,"batteryLevel":88,"time":1629391435},"lastHeard":1629393577,"snr":4.5},
|
||||
{"num":84682040,"user":{"id":"!050c2538","longName":"Yellow Beam","shortName":"YB","macaddr":"PGEFDCU4","hwModel":"TBEAM"},"position":{"latitudeI":476020703,"longitudeI":-1221531973,"altitude":79,"batteryLevel":1,"time":1631593233},"lastHeard":1631593034,"snr":5.0},
|
||||
{"num":2354994191,"user":{"id":"!8c5e5c0f","longName":"RAK Solar 3","shortName":"RS3","macaddr":"+GKMXlwP","hwModel":"RAK4631"},"position":{"batteryLevel":91,"time":1629263310},"lastHeard":1629393330,"snr":4.5},
|
||||
{"num":2718727166,"user":{"id":"!a20c7bfe","longName":"RAK Large Node","shortName":"RLN","macaddr":"zXSiDHv+","hwModel":"RAK4631"},"position":{"batteryLevel":32,"time":1629061939},"lastHeard":1629102457,"snr":-17.5},
|
||||
{"num":84681200,"user":{"id":"!050c21f0","longName":"Unknown 21f0","shortName":"?F0","macaddr":"PGEFDCHw","hwModel":"TBEAM"},"position":{"latitudeI":476022115,"longitudeI":-1221531952,"altitude":85,"batteryLevel":100,"time":1631593830},"lastHeard":1631593584,"snr":6.75},
|
||||
{"num":2930161432,"user":{"id":"!aea6b718","longName":"Unknown b718","shortName":"?18","macaddr":"TBGuprcY","hwModel":"TBEAM"},"position":{"latitudeI":476020757,"longitudeI":-1221533124,"altitude":56,"batteryLevel":100,"time":1631593558},"lastHeard":1631593554,"snr":6.75},
|
||||
{"num":4064637200,"user":{"id":"!f2457110","longName":"Unknown 7110","shortName":"?10","macaddr":"CDryRXEQ","hwModel":"TBEAM"},"position":{"latitudeI":476021534,"longitudeI":-1221533621,"altitude":49,"batteryLevel":100,"time":1631593778},"lastHeard":1631593533,"snr":7.0}
|
||||
|
||||
]
|
||||
|
|
|
|||
43
MeshtasticClient/Resources/nodeInfoModel.json
Normal file
43
MeshtasticClient/Resources/nodeInfoModel.json
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
[
|
||||
{
|
||||
"num":2792101487,
|
||||
"user":{
|
||||
"id":"!a66c166f",
|
||||
"longName":"RAK Solar 2",
|
||||
"shortName":"RS2",
|
||||
"macaddr":"8eambBZv",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"batteryLevel":68},
|
||||
"lastHeard":1631593661
|
||||
}
|
||||
},
|
||||
{
|
||||
"num":1000569662,
|
||||
"user":{
|
||||
"id":"!3ba37b3e",
|
||||
"longName":"RAK Solar 1",
|
||||
"shortName":"RS1",
|
||||
"macaddr":"1Kc7o3s+",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476021390,
|
||||
"longitudeI":-1221532609,
|
||||
"altitude":71,
|
||||
"batteryLevel":70,
|
||||
"time":1629314497
|
||||
},
|
||||
"lastHeard":1629392801,
|
||||
"snr":5.25
|
||||
},
|
||||
{"num":1133445808,"user":{"id":"!438f02b0","longName":"RAK DEV NODE","shortName":"RDN","macaddr":"92VDjwKw","hwModel":"RAK4631"},"position":{"latitudeI":476022071,"longitudeI":-1221533607,"altitude":91,"batteryLevel":88,"time":1629391435},"lastHeard":1629393577,"snr":4.5},
|
||||
{"num":84682040,"user":{"id":"!050c2538","longName":"Yellow Beam","shortName":"YB","macaddr":"PGEFDCU4","hwModel":"TBEAM"},"position":{"latitudeI":476020703,"longitudeI":-1221531973,"altitude":79,"batteryLevel":1,"time":1631593233},"lastHeard":1631593034,"snr":5.0},
|
||||
{"num":2354994191,"user":{"id":"!8c5e5c0f","longName":"RAK Solar 3","shortName":"RS3","macaddr":"+GKMXlwP","hwModel":"RAK4631"},"position":{"batteryLevel":91,"time":1629263310},"lastHeard":1629393330,"snr":4.5},
|
||||
{"num":2718727166,"user":{"id":"!a20c7bfe","longName":"RAK Large Node","shortName":"RLN","macaddr":"zXSiDHv+","hwModel":"RAK4631"},"position":{"batteryLevel":32,"time":1629061939},"lastHeard":1629102457,"snr":-17.5},
|
||||
{"num":84681200,"user":{"id":"!050c21f0","longName":"Unknown 21f0","shortName":"?F0","macaddr":"PGEFDCHw","hwModel":"TBEAM"},"position":{"latitudeI":476022115,"longitudeI":-1221531952,"altitude":85,"batteryLevel":100,"time":1631593830},"lastHeard":1631593584,"snr":6.75},
|
||||
{"num":2930161432,"user":{"id":"!aea6b718","longName":"Unknown b718","shortName":"?18","macaddr":"TBGuprcY","hwModel":"TBEAM"},"position":{"latitudeI":476020757,"longitudeI":-1221533124,"altitude":56,"batteryLevel":100,"time":1631593558},"lastHeard":1631593554,"snr":6.75},
|
||||
{"num":4064637200,"user":{"id":"!f2457110","longName":"Unknown 7110","shortName":"?10","macaddr":"CDryRXEQ","hwModel":"TBEAM"},"position":{"latitudeI":476021534,"longitudeI":-1221533621,"altitude":49,"batteryLevel":100,"time":1631593778},"lastHeard":1631593533,"snr":7.0}
|
||||
|
||||
]
|
||||
|
|
@ -1,149 +1,152 @@
|
|||
[
|
||||
{
|
||||
"from":1133445808,
|
||||
"to":1133445808,
|
||||
"decoded":{
|
||||
"portnum":"ADMIN_APP",
|
||||
"payload":"b"":\\x04\\x08\\x01\\x12\\x00",
|
||||
"requestId":1506683854,
|
||||
"admin":{
|
||||
"getChannelResponse":{
|
||||
"index":1,
|
||||
"settings":{
|
||||
|
||||
}
|
||||
},
|
||||
"raw":"get_channel_response"{
|
||||
"index":1 settings{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id":1481765942,
|
||||
"rxTime":1630360112,
|
||||
"hopLimit":3,
|
||||
"priority":"RELIABLE",
|
||||
"raw":"from":"1133445808 to":1133445808 decoded{
|
||||
"portnum":"ADMIN_APP payload":":\\004\\010\\001\\022\\000""request_id":1506683854
|
||||
}"id":"1481765942 rx_time":"1630360112 hop_limit":"3 priority":"RELIABLE",
|
||||
"fromId":"!438f02b0",
|
||||
"toId":"!438f02b0"
|
||||
}{
|
||||
"num":1133445808,
|
||||
"user":{
|
||||
"id":"!438f02b0",
|
||||
"longName":"RAK DEV NODE",
|
||||
"shortName":"RDN",
|
||||
"macaddr":"92VDjwKw",
|
||||
"hwModel":"RAK4631",
|
||||
"raw":"id":"!438f02b0""long_name":"RAK DEV NODE""short_name":"RDN""macaddr":"\\367eC\\217\\002\\260""hw_model":RAK4631
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476021540,
|
||||
"longitudeI":-1221532059,
|
||||
"altitude":111,
|
||||
"time":1630360110,
|
||||
"latitude":47.602154,
|
||||
"longitude":-122.15320589999999
|
||||
},
|
||||
"lastHeard":1630360100,
|
||||
"lastReceived":{
|
||||
"from":1133445808,
|
||||
"to":4294967295,
|
||||
"decoded":{
|
||||
"portnum":"NODEINFO_APP",
|
||||
"payload":"b""\n\t!438f02b0\\x12\\x0cRAK DEV NODE\\x1a\\x03RDN\"\\x06\\xf7eC\\x8f\\x02\\xb00\t",
|
||||
"wantResponse":true,
|
||||
"user":{
|
||||
"id":"!438f02b0",
|
||||
"longName":"RAK DEV NODE",
|
||||
"shortName":"RDN",
|
||||
"macaddr":"92VDjwKw",
|
||||
"hwModel":"RAK4631",
|
||||
"raw":"id":"!438f02b0""long_name":"RAK DEV NODE""short_name":"RDN""macaddr":"\\367eC\\217\\002\\260""hw_model":RAK4631
|
||||
}
|
||||
},
|
||||
"id":1481765939,
|
||||
"rxTime":1630360100,
|
||||
"hopLimit":3,
|
||||
"priority":"BACKGROUND",
|
||||
"raw":"from":"1133445808 to":4294967295 decoded{
|
||||
"portnum":"NODEINFO_APP payload":"\n\t!438f02b0\\022\\014RAK DEV NODE\\032\\003RDN\"\\006\\367eC\\217\\002\\2600\t""want_response":true
|
||||
}"id":"1481765939 rx_time":"1630360100 hop_limit":"3 priority":"BACKGROUND",
|
||||
"fromId":"!438f02b0",
|
||||
"toId":"^all"
|
||||
},
|
||||
"snr":"None",
|
||||
"hopLimit":3
|
||||
}{
|
||||
"num":1000569662,
|
||||
"user":{
|
||||
"id":"!3ba37b3e",
|
||||
"longName":"RAK Solar 1",
|
||||
"shortName":"RS1",
|
||||
"macaddr":"1Kc7o3s+",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476022865,
|
||||
"longitudeI":-1221531705,
|
||||
"altitude":81,
|
||||
"batteryLevel":4,
|
||||
"time":1628091161,
|
||||
"latitude":47.6022865,
|
||||
"longitude":-122.15317049999999
|
||||
},
|
||||
"lastHeard":1630234276,
|
||||
"snr":5.25
|
||||
}{
|
||||
"num":2792101487,
|
||||
"user":{
|
||||
"id":"!a66c166f",
|
||||
"longName":"RAK Solar 2",
|
||||
"shortName":"RS2",
|
||||
"macaddr":"8eambBZv",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"batteryLevel":56,
|
||||
"time":1628096176
|
||||
},
|
||||
"lastHeard":1628231149,
|
||||
"snr":4.75
|
||||
}{
|
||||
"num":84682040,
|
||||
"user":{
|
||||
"id":"!050c2538",
|
||||
"longName":"Yellow Beam",
|
||||
"shortName":"YB",
|
||||
"macaddr":"PGEFDCU4",
|
||||
"hwModel":"TBEAM"
|
||||
},
|
||||
"position":{
|
||||
"latitudeI":476020441,
|
||||
"longitudeI":-1221533598,
|
||||
"altitude":65,
|
||||
"batteryLevel":100,
|
||||
"time":1628405738,
|
||||
"latitude":47.6020441,
|
||||
"longitude":-122.15335979999999
|
||||
},
|
||||
"lastHeard":1628405744,
|
||||
"snr":4.5
|
||||
}{
|
||||
"num":2354994191,
|
||||
"user":{
|
||||
"id":"!8c5e5c0f",
|
||||
"longName":"RAK Solar 3",
|
||||
"shortName":"RS3",
|
||||
"macaddr":"+GKMXlwP",
|
||||
"hwModel":"RAK4631"
|
||||
},
|
||||
"position":{
|
||||
"batteryLevel":62
|
||||
},
|
||||
"lastHeard":1630252441,
|
||||
"snr":4.75
|
||||
}
|
||||
]
|
||||
[{
|
||||
"num": 2792101487,
|
||||
"user": {
|
||||
"id": "!a66c166f",
|
||||
"longName": "RAK Solar 2",
|
||||
"shortName": "RS2",
|
||||
"macaddr": "8eambBZv",
|
||||
"hwModel": "RAK4631"
|
||||
},
|
||||
"position": {
|
||||
"batteryLevel": 68
|
||||
},
|
||||
"lastHeard": 1631593661
|
||||
}, {
|
||||
"num": 1000569662,
|
||||
"user": {
|
||||
"id": "!3ba37b3e",
|
||||
"longName": "RAK Solar 1",
|
||||
"shortName": "RS1",
|
||||
"macaddr": "1Kc7o3s+",
|
||||
"hwModel": "RAK4631"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476021390,
|
||||
"longitudeI": -1221532609,
|
||||
"altitude": 71,
|
||||
"batteryLevel": 70,
|
||||
"time": 1629314497
|
||||
},
|
||||
"lastHeard": 1629392801,
|
||||
"snr": 5.25
|
||||
}, {
|
||||
"num": 1133445808,
|
||||
"user": {
|
||||
"id": "!438f02b0",
|
||||
"longName": "RAK DEV NODE",
|
||||
"shortName": "RDN",
|
||||
"macaddr": "92VDjwKw",
|
||||
"hwModel": "RAK4631"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476022071,
|
||||
"longitudeI": -1221533607,
|
||||
"altitude": 91,
|
||||
"batteryLevel": 88,
|
||||
"time": 1629391435
|
||||
},
|
||||
"lastHeard": 1629393577,
|
||||
"snr": 4.5
|
||||
}, {
|
||||
"num": 84682040,
|
||||
"user": {
|
||||
"id": "!050c2538",
|
||||
"longName": "Yellow Beam",
|
||||
"shortName": "YB",
|
||||
"macaddr": "PGEFDCU4",
|
||||
"hwModel": "TBEAM"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476020703,
|
||||
"longitudeI": -1221531973,
|
||||
"altitude": 79,
|
||||
"batteryLevel": 1,
|
||||
"time": 1631593233
|
||||
},
|
||||
"lastHeard": 1631593034,
|
||||
"snr": 5.0
|
||||
}, {
|
||||
"num": 2354994191,
|
||||
"user": {
|
||||
"id": "!8c5e5c0f",
|
||||
"longName": "RAK Solar 3",
|
||||
"shortName": "RS3",
|
||||
"macaddr": "+GKMXlwP",
|
||||
"hwModel": "RAK4631"
|
||||
},
|
||||
"position": {
|
||||
"batteryLevel": 91,
|
||||
"time": 1629263310
|
||||
},
|
||||
"lastHeard": 1629393330,
|
||||
"snr": 4.5
|
||||
}, {
|
||||
"num": 2718727166,
|
||||
"user": {
|
||||
"id": "!a20c7bfe",
|
||||
"longName": "RAK Large Node",
|
||||
"shortName": "RLN",
|
||||
"macaddr": "zXSiDHv+",
|
||||
"hwModel": "RAK4631"
|
||||
},
|
||||
"position": {
|
||||
"batteryLevel": 32,
|
||||
"time": 1629061939
|
||||
},
|
||||
"lastHeard": 1629102457,
|
||||
"snr": -17.5
|
||||
}, {
|
||||
"num": 84681200,
|
||||
"user": {
|
||||
"id": "!050c21f0",
|
||||
"longName": "Unknown 21f0",
|
||||
"shortName": "?F0",
|
||||
"macaddr": "PGEFDCHw",
|
||||
"hwModel": "TBEAM"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476022115,
|
||||
"longitudeI": -1221531952,
|
||||
"altitude": 85,
|
||||
"batteryLevel": 100,
|
||||
"time": 1631593830
|
||||
},
|
||||
"lastHeard": 1631593584,
|
||||
"snr": 6.75
|
||||
}, {
|
||||
"num": 2930161432,
|
||||
"user": {
|
||||
"id": "!aea6b718",
|
||||
"longName": "Unknown b718",
|
||||
"shortName": "?18",
|
||||
"macaddr": "TBGuprcY",
|
||||
"hwModel": "TBEAM"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476020757,
|
||||
"longitudeI": -1221533124,
|
||||
"altitude": 56,
|
||||
"batteryLevel": 100,
|
||||
"time": 1631593558
|
||||
},
|
||||
"lastHeard": 1631593554,
|
||||
"snr": 6.75
|
||||
}, {
|
||||
"num": 4064637200,
|
||||
"user": {
|
||||
"id": "!f2457110",
|
||||
"longName": "Unknown 7110",
|
||||
"shortName": "?10",
|
||||
"macaddr": "CDryRXEQ",
|
||||
"hwModel": "TBEAM"
|
||||
},
|
||||
"position": {
|
||||
"latitudeI": 476021534,
|
||||
"longitudeI": -1221533621,
|
||||
"altitude": 49,
|
||||
"batteryLevel": 100,
|
||||
"time": 1631593778
|
||||
},
|
||||
"lastHeard": 1631593533,
|
||||
"snr": 7.0
|
||||
}]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ struct ContentView: View {
|
|||
case featured
|
||||
case list
|
||||
case ble
|
||||
case nodes
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -33,6 +34,11 @@ struct ContentView: View {
|
|||
Label("Devices", systemImage: "flipphone")
|
||||
}
|
||||
.tag(Tab.devices)
|
||||
NodeList()
|
||||
.tabItem {
|
||||
Label("Nodes", systemImage: "flipphone")
|
||||
}
|
||||
.tag(Tab.nodes)
|
||||
DeviceBLE()
|
||||
.tabItem {
|
||||
Label("Bluetooth", systemImage: "dot.radiowaves.left.and.right")
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ struct DeviceDetail: View {
|
|||
var deviceIndex: Int {
|
||||
modelData.devices.firstIndex(where: { $0.id == device.id })!
|
||||
}
|
||||
|
||||
struct MapLocation: Identifiable {
|
||||
let id = UUID()
|
||||
let name: String
|
||||
|
|
|
|||
|
|
@ -40,21 +40,25 @@ struct DeviceMap: View {
|
|||
MapLocation(name: devices[3].shortName, coordinate: CLLocationCoordinate2D(latitude: devices[3].position.latitude, longitude: devices[3].position.longitude))
|
||||
]
|
||||
|
||||
ZStack {
|
||||
Map(coordinateRegion: regionBinding,
|
||||
interactionModes: [.all],
|
||||
showsUserLocation: true,
|
||||
userTrackingMode: .constant(.follow), annotationItems: annotations) { location in
|
||||
|
||||
MapAnnotation(
|
||||
coordinate: location.coordinate,
|
||||
content: {
|
||||
Text(location.name).font(.caption2).foregroundColor(.white)
|
||||
.background(Circle()
|
||||
.fill(Color.blue)
|
||||
.frame(width: 40, height: 40)) }
|
||||
)
|
||||
}.frame(maxHeight:.infinity)
|
||||
}
|
||||
NavigationView {
|
||||
ZStack {
|
||||
Map(coordinateRegion: regionBinding,
|
||||
interactionModes: [.all],
|
||||
showsUserLocation: true,
|
||||
userTrackingMode: .constant(.follow), annotationItems: annotations) { location in
|
||||
|
||||
MapAnnotation(
|
||||
coordinate: location.coordinate,
|
||||
content: {
|
||||
Text(location.name).font(.caption2).foregroundColor(.white)
|
||||
.background(Circle()
|
||||
.fill(Color.blue)
|
||||
.frame(width: 40, height: 40)) }
|
||||
)
|
||||
}.frame(maxHeight:.infinity)
|
||||
}
|
||||
.navigationTitle("Mesh Map")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct CircleImage: View {
|
|||
|
||||
var body: some View {
|
||||
image
|
||||
.resizable()
|
||||
.clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
|
||||
.overlay(Circle().stroke(Color.white, lineWidth: 4))
|
||||
.shadow(radius: 7)
|
||||
|
|
|
|||
26
MeshtasticClient/Views/Helpers/CircleText.swift
Normal file
26
MeshtasticClient/Views/Helpers/CircleText.swift
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
A view that clips an image to a circle and adds a stroke and shadow.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CircleText: View {
|
||||
var text: String
|
||||
|
||||
var body: some View {
|
||||
|
||||
Text(text).font(.subheadline).foregroundColor(.white)
|
||||
.background(Circle()
|
||||
.fill(Color.blue)
|
||||
.frame(width: 40, height: 40, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/))
|
||||
}
|
||||
}
|
||||
|
||||
struct CircleText_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CircleText(text: "RDN")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import CoreLocation
|
|||
|
||||
struct Messages: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
NavigationView {
|
||||
|
||||
List {
|
||||
HStack {
|
||||
|
|
@ -50,8 +50,8 @@ struct Messages: View {
|
|||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Broadcast Channel")
|
||||
}
|
||||
}.navigationTitle("Broadcast Channel")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
129
MeshtasticClient/Views/Nodes/NodeDetail.swift
Normal file
129
MeshtasticClient/Views/Nodes/NodeDetail.swift
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
A view showing the details for a device.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
import MapKit
|
||||
import CoreLocation
|
||||
import CoreBluetooth
|
||||
|
||||
struct NodeDetail: View {
|
||||
|
||||
@EnvironmentObject var modelData: ModelData
|
||||
var node: NodeInfoModel
|
||||
|
||||
var nodeIndex: Int {
|
||||
modelData.nodes.firstIndex(where: { $0.id == node.id })!
|
||||
}
|
||||
|
||||
struct MapLocation: Identifiable {
|
||||
let id = UUID()
|
||||
let name: String
|
||||
let coordinate: CLLocationCoordinate2D
|
||||
}
|
||||
var body: some View {
|
||||
let location = LocationHelper.currentLocation
|
||||
let currentCoordinatePosition = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
|
||||
let regionBinding = Binding<MKCoordinateRegion>(
|
||||
get: {
|
||||
MKCoordinateRegion(center: currentCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02))
|
||||
},
|
||||
set: { _ in }
|
||||
)
|
||||
|
||||
GeometryReader { bounds in
|
||||
|
||||
VStack {
|
||||
|
||||
// Map or Device Image
|
||||
if(node.position.latitudeI != nil && node.position.latitudeI! > 0) {
|
||||
Map(coordinateRegion: regionBinding, showsUserLocation: true, userTrackingMode: .constant(.follow))
|
||||
|
||||
.frame(idealWidth: bounds.size.width, minHeight: bounds.size.height / 2)
|
||||
}
|
||||
else
|
||||
{
|
||||
Image(node.user.hwModel.lowercased())
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: bounds.size.width, height: bounds.size.height / 2)
|
||||
}
|
||||
ScrollView {
|
||||
HStack {
|
||||
Spacer()
|
||||
Image(systemName: "flipphone").font(.largeTitle).foregroundColor(.blue)
|
||||
Text("Model: " + String(node.user.hwModel)).font(.title)
|
||||
Spacer()
|
||||
}.padding()
|
||||
Divider()
|
||||
HStack {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right").font(.title2).foregroundColor(.blue)
|
||||
VStack(alignment: .center) {
|
||||
|
||||
Text("SNR").font(.title3)
|
||||
Text(String(node.snr!)).font(.title3).foregroundColor(.gray)
|
||||
}
|
||||
Divider()
|
||||
VStack(alignment: .center) {
|
||||
|
||||
Text("AKA").font(.title3)
|
||||
Text(node.user.shortName).font(.title3).foregroundColor(.gray)
|
||||
}
|
||||
Divider()
|
||||
VStack(alignment: .leading) {
|
||||
Text("Battery").font(.title3)
|
||||
Text(String(node.position.batteryLevel!) + "%").font(.title3).foregroundColor(.gray)
|
||||
}
|
||||
}.padding(4)
|
||||
Divider()
|
||||
HStack{
|
||||
Image(systemName: "clock").font(.title2).foregroundColor(.blue)
|
||||
let lastHeard = Date(timeIntervalSince1970: node.lastHeard)
|
||||
Text("Last Heard:").font(.title3)
|
||||
Text(lastHeard, style: .relative).font(.title3)
|
||||
Text("ago").font(.title3)
|
||||
}.padding()
|
||||
Divider()
|
||||
HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 14) {
|
||||
Image(systemName: "mappin").font(.title).foregroundColor(.blue)
|
||||
VStack(alignment: .leading) {
|
||||
Text("Latitude").font(.headline)
|
||||
Text(String(node.position.latitudeI!)).font(.caption).foregroundColor(.gray)
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text("Longitude").font(.headline)
|
||||
Text(String(node.position.longitudeI!)).font(.caption).foregroundColor(.gray)
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text("Altitude").font(.headline)
|
||||
Text(String(node.position.altitude!) + " m").font(.caption).foregroundColor(.gray)
|
||||
}
|
||||
}.padding()
|
||||
Divider()
|
||||
HStack {
|
||||
Spacer()
|
||||
Image(systemName: "person").font(.title3).foregroundColor(.blue)
|
||||
Text("Unique Id: " + String(node.user.id)).font(.headline)
|
||||
Divider()
|
||||
Image(systemName: "number").font(.title3).foregroundColor(.blue)
|
||||
Text("Node Num: " + String(node.num)).font(.headline)
|
||||
Spacer()
|
||||
}.padding()
|
||||
}
|
||||
}.navigationTitle(node.user.longName)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarItems(trailing:
|
||||
HStack {
|
||||
|
||||
CircleText(text: node.user.shortName).offset(y: -2)
|
||||
|
||||
}
|
||||
)
|
||||
}.ignoresSafeArea(.all, edges: [.leading, .trailing])
|
||||
|
||||
}
|
||||
}
|
||||
41
MeshtasticClient/Views/Nodes/NodeList.swift
Normal file
41
MeshtasticClient/Views/Nodes/NodeList.swift
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// DeviceHome.swift
|
||||
// MeshtasticClient
|
||||
//
|
||||
// Created by Garth Vander Houwen on 8/7/21.
|
||||
//
|
||||
|
||||
// Abstract:
|
||||
// A view showing a list of devices that have been seen on the mesh network
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NodeList: View {
|
||||
@EnvironmentObject var modelData: ModelData
|
||||
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
|
||||
List {
|
||||
|
||||
|
||||
ForEach(modelData.nodes) { node in
|
||||
NavigationLink(destination: NodeDetail(node: node)) {
|
||||
NodeRow(node: node)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("All Nodes")
|
||||
|
||||
|
||||
}.navigationViewStyle(StackNavigationViewStyle()) // Force Full screen master details
|
||||
}
|
||||
}
|
||||
|
||||
struct NodeList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NodeList()
|
||||
.environmentObject(ModelData())
|
||||
}
|
||||
}
|
||||
49
MeshtasticClient/Views/Nodes/NodeRow.swift
Normal file
49
MeshtasticClient/Views/Nodes/NodeRow.swift
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// DeviceMap.swift
|
||||
// MeshtasticClient
|
||||
//
|
||||
// Created by Garth Vander Houwen on 8/7/21.
|
||||
//
|
||||
// Abstract:
|
||||
// A single row to be displayed in a list of landmarks.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NodeRow: View {
|
||||
var node: NodeInfoModel
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Image(node.user.hwModel.lowercased()).resizable().frame(width: 150, height: 150)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
|
||||
Text(node.user.longName).font(.title2)
|
||||
HStack {
|
||||
if node.user.hwModel == "TBEAM" || node.user.hwModel == "TLORA" {
|
||||
Image(systemName: "wifi")
|
||||
.foregroundColor(.blue).font(.title3)
|
||||
}
|
||||
if false {
|
||||
Image(systemName: "rectangle.connected.to.line.below")
|
||||
.foregroundColor(.green).font(.title2)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NodeRow_Previews: PreviewProvider {
|
||||
static var nodes = ModelData().nodes
|
||||
|
||||
static var previews: some View {
|
||||
Group {
|
||||
NodeRow(node: nodes[0])
|
||||
NodeRow(node: nodes[1])
|
||||
NodeRow(node: nodes[2])
|
||||
}
|
||||
.previewLayout(.fixed(width: 300, height: 70))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue