mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Start work to fix the broken node map view
Tidy up suggested mqtt topics
This commit is contained in:
parent
d84f2ad91a
commit
d5f5d70364
4 changed files with 151 additions and 115 deletions
|
|
@ -28,7 +28,47 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
case my_919 = 17
|
||||
case sg_923 = 18
|
||||
case lora24 = 13
|
||||
|
||||
var topic: String {
|
||||
switch self {
|
||||
case .unset:
|
||||
"UNSET"
|
||||
case .us:
|
||||
"US"
|
||||
case .eu433:
|
||||
"EU_433"
|
||||
case .eu868:
|
||||
"EU_868"
|
||||
case .cn:
|
||||
"CN"
|
||||
case .jp:
|
||||
"JP"
|
||||
case .anz:
|
||||
"ANZ"
|
||||
case .kr:
|
||||
"KR"
|
||||
case .tw:
|
||||
"TW"
|
||||
case .ru:
|
||||
"RU"
|
||||
case .in:
|
||||
"IN"
|
||||
case .nz865:
|
||||
"NZ_865"
|
||||
case .th:
|
||||
"TH"
|
||||
case .ua433:
|
||||
"UA_433"
|
||||
case .ua868:
|
||||
"UA_868"
|
||||
case .my_433:
|
||||
"MY_433"
|
||||
case .my_919:
|
||||
"MY_919"
|
||||
case .sg_923:
|
||||
"SG_923"
|
||||
case .lora24:
|
||||
"LORA_24"
|
||||
} }
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
switch self {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import CoreLocation
|
|||
#if canImport(MapKit)
|
||||
import MapKit
|
||||
#endif
|
||||
import WeatherKit
|
||||
|
||||
@available(iOS 17.0, macOS 14.0, *)
|
||||
struct NodeMapSwiftUI: View {
|
||||
|
|
@ -60,6 +59,15 @@ struct NodeMapSwiftUI: View {
|
|||
Map(position: $position, bounds: MapCameraBounds(minimumDistance: 1, maximumDistance: .infinity), scope: mapScope) {
|
||||
/// Node Color from node.num
|
||||
let nodeColor = UIColor(hex: UInt32(node.num))
|
||||
/// Convex Hull
|
||||
if showConvexHull {
|
||||
if lineCoords.count > 0 {
|
||||
let hull = lineCoords.getConvexHull()
|
||||
MapPolygon(coordinates: hull)
|
||||
.stroke(Color(nodeColor.darker()), lineWidth: 3)
|
||||
.foregroundStyle(Color(nodeColor).opacity(0.4))
|
||||
}
|
||||
}
|
||||
/// Route Lines
|
||||
if showRouteLines {
|
||||
let gradient = LinearGradient(
|
||||
|
|
@ -73,114 +81,96 @@ struct NodeMapSwiftUI: View {
|
|||
MapPolyline(coordinates: lineCoords)
|
||||
.stroke(gradient, style: dashed)
|
||||
}
|
||||
/// Convex Hull
|
||||
if showConvexHull {
|
||||
if lineCoords.count > 0 {
|
||||
let hull = lineCoords.getConvexHull()
|
||||
MapPolygon(coordinates: hull)
|
||||
.stroke(Color(nodeColor.darker()), lineWidth: 3)
|
||||
.foregroundStyle(Color(nodeColor).opacity(0.4))
|
||||
}
|
||||
}
|
||||
|
||||
/// Waypoint Annotations
|
||||
if waypoints.count > 0 && showWaypoints {
|
||||
ForEach(Array(waypoints), id: \.id) { waypoint in
|
||||
Annotation(waypoint.name ?? "?", coordinate: waypoint.coordinate) {
|
||||
LazyVStack {
|
||||
CircleText(text: String(UnicodeScalar(Int(waypoint.icon)) ?? "📍"), color: Color.orange, circleSize: 35)
|
||||
.onTapGesture(coordinateSpace: .named("nodemap")) { location in
|
||||
selectedWaypoint = (selectedWaypoint == waypoint ? nil : waypoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Node Annotations
|
||||
ForEach(positionArray, id: \.id) { position in
|
||||
let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 771))
|
||||
let headingDegrees = Angle.degrees(Double(position.heading))
|
||||
/// Reduced Precision Map Circle
|
||||
if position.latest && 11...16 ~= position.precisionBits {
|
||||
let pp = PositionPrecision(rawValue: Int(position.precisionBits))
|
||||
let radius : CLLocationDistance = pp?.precisionMeters ?? 0
|
||||
if radius > 0.0 {
|
||||
MapCircle(center: position.coordinate, radius: radius)
|
||||
.foregroundStyle(Color(nodeColor).opacity(0.25))
|
||||
.stroke(.white, lineWidth: 2)
|
||||
// /// Reduced Precision Map Circle
|
||||
// if position.latest && 11...16 ~= position.precisionBits {
|
||||
// let pp = PositionPrecision(rawValue: Int(position.precisionBits))
|
||||
// let radius : CLLocationDistance = pp?.precisionMeters ?? 0
|
||||
// if radius > 0.0 {
|
||||
// MapCircle(center: position.coordinate, radius: radius)
|
||||
// .foregroundStyle(Color(nodeColor).opacity(0.25))
|
||||
// .stroke(.white, lineWidth: 2)
|
||||
// }
|
||||
// }
|
||||
// Annotation(position.latest ? node.user?.shortName ?? "?": "", coordinate: position.coordinate) {
|
||||
// LazyVStack {
|
||||
// if position.latest {
|
||||
// ZStack {
|
||||
// Circle()
|
||||
// .fill(Color(nodeColor.lighter()).opacity(0.4).shadow(.drop(color: Color(nodeColor).isLight() ? .black : .white, radius: 5)))
|
||||
// .foregroundStyle(Color(nodeColor.lighter()).opacity(0.3))
|
||||
// .frame(width: 50, height: 50)
|
||||
// if pf.contains(.Heading) {
|
||||
// Image(systemName: pf.contains(.Speed) && position.speed > 1 ? "location.north" : "octagon")
|
||||
// .symbolEffect(.pulse.byLayer)
|
||||
// .padding(5)
|
||||
// .foregroundStyle(Color(nodeColor).isLight() ? .black : .white)
|
||||
// .background(Color(nodeColor.darker()))
|
||||
// .clipShape(Circle())
|
||||
// .rotationEffect(headingDegrees)
|
||||
// .onTapGesture {
|
||||
// selectedPosition = (selectedPosition == position ? nil : position)
|
||||
// }
|
||||
// .popover(item: $selectedPosition) { selection in
|
||||
// PositionPopover(position: selection)
|
||||
// .padding()
|
||||
// .opacity(0.8)
|
||||
// .presentationCompactAdaptation(.popover)
|
||||
// }
|
||||
//
|
||||
// } else {
|
||||
// Image(systemName: "flipphone")
|
||||
// .symbolEffect(.pulse.byLayer)
|
||||
// .padding(5)
|
||||
// .foregroundStyle(Color(nodeColor).isLight() ? .black : .white)
|
||||
// .background(Color(UIColor(hex: UInt32(node.num)).darker()))
|
||||
// .clipShape(Circle())
|
||||
// .onTapGesture {
|
||||
// selectedPosition = (selectedPosition == position ? nil : position)
|
||||
// }
|
||||
// .popover(item: $selectedPosition) { selection in
|
||||
// PositionPopover(position: selection)
|
||||
// .padding()
|
||||
// .opacity(0.8)
|
||||
// .presentationCompactAdaptation(.popover)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if showNodeHistory {
|
||||
// if pf.contains(.Heading) {
|
||||
// Image(systemName: "location.north.circle")
|
||||
// .resizable()
|
||||
// .scaledToFit()
|
||||
// .foregroundStyle(Color(UIColor(hex: UInt32(node.num))).isLight() ? .black : .white)
|
||||
// .background(Color(UIColor(hex: UInt32(node.num))))
|
||||
// .clipShape(Circle())
|
||||
// .rotationEffect(headingDegrees)
|
||||
// .frame(width: 16, height: 16)
|
||||
//
|
||||
// } else {
|
||||
// Circle()
|
||||
// .fill(Color(UIColor(hex: UInt32(node.num))))
|
||||
// .strokeBorder(Color(UIColor(hex: UInt32(node.num))).isLight() ? .black : .white ,lineWidth: 2)
|
||||
// .frame(width: 12, height: 12)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Annotation(position.latest ? node.user?.shortName ?? "?": "", coordinate: position.coordinate) {
|
||||
LazyVStack {
|
||||
if position.latest {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color(nodeColor.lighter()).opacity(0.4).shadow(.drop(color: Color(nodeColor).isLight() ? .black : .white, radius: 5)))
|
||||
.foregroundStyle(Color(nodeColor.lighter()).opacity(0.3))
|
||||
.frame(width: 50, height: 50)
|
||||
if pf.contains(.Heading) {
|
||||
Image(systemName: pf.contains(.Speed) && position.speed > 1 ? "location.north" : "octagon")
|
||||
.symbolEffect(.pulse.byLayer)
|
||||
.padding(5)
|
||||
.foregroundStyle(Color(nodeColor).isLight() ? .black : .white)
|
||||
.background(Color(nodeColor.darker()))
|
||||
.clipShape(Circle())
|
||||
.rotationEffect(headingDegrees)
|
||||
.onTapGesture {
|
||||
selectedPosition = (selectedPosition == position ? nil : position)
|
||||
}
|
||||
.popover(item: $selectedPosition) { selection in
|
||||
PositionPopover(position: selection)
|
||||
.padding()
|
||||
.opacity(0.8)
|
||||
.presentationCompactAdaptation(.popover)
|
||||
}
|
||||
|
||||
} else {
|
||||
Image(systemName: "flipphone")
|
||||
.symbolEffect(.pulse.byLayer)
|
||||
.padding(5)
|
||||
.foregroundStyle(Color(nodeColor).isLight() ? .black : .white)
|
||||
.background(Color(UIColor(hex: UInt32(node.num)).darker()))
|
||||
.clipShape(Circle())
|
||||
.onTapGesture {
|
||||
selectedPosition = (selectedPosition == position ? nil : position)
|
||||
}
|
||||
.popover(item: $selectedPosition) { selection in
|
||||
PositionPopover(position: selection)
|
||||
.padding()
|
||||
.opacity(0.8)
|
||||
.presentationCompactAdaptation(.popover)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if showNodeHistory {
|
||||
if pf.contains(.Heading) {
|
||||
Image(systemName: "location.north.circle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.foregroundStyle(Color(UIColor(hex: UInt32(node.num))).isLight() ? .black : .white)
|
||||
.background(Color(UIColor(hex: UInt32(node.num))))
|
||||
.clipShape(Circle())
|
||||
.rotationEffect(headingDegrees)
|
||||
.frame(width: 16, height: 16)
|
||||
|
||||
} else {
|
||||
Circle()
|
||||
.fill(Color(UIColor(hex: UInt32(node.num))))
|
||||
.strokeBorder(Color(UIColor(hex: UInt32(node.num))).isLight() ? .black : .white ,lineWidth: 2)
|
||||
.frame(width: 12, height: 12)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tag(position.time)
|
||||
.annotationTitles(.automatic)
|
||||
.annotationSubtitles(.automatic)
|
||||
}
|
||||
// }
|
||||
// .tag(position.time)
|
||||
// .annotationTitles(.automatic)
|
||||
// .annotationSubtitles(.automatic)
|
||||
// }
|
||||
}
|
||||
.mapScope(mapScope)
|
||||
.mapStyle(mapStyle)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ struct MQTTConfig: View {
|
|||
@State var root = "msh"
|
||||
@State var selectedTopic = ""
|
||||
@State var mqttConnected: Bool = false
|
||||
@State var defaultTopic = "msh/US"
|
||||
@State var nearbyTopics = [String]()
|
||||
let locale = Locale.current
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
|
|
@ -315,6 +317,8 @@ struct MQTTConfig: View {
|
|||
nearbyTopics = []
|
||||
let geocoder = CLGeocoder()
|
||||
if LocationsHandler.shared.locationsArray.count > 0 {
|
||||
let region = RegionCodes(rawValue: Int(node?.loRaConfig?.regionCode ?? 0))?.topic
|
||||
defaultTopic = "msh/" + (region ?? "UNSET")
|
||||
geocoder.reverseGeocodeLocation(LocationsHandler.shared.locationsArray.first!, completionHandler: {(placemarks, error) -> Void in
|
||||
if error != nil {
|
||||
print("Failed to reverse geocode location")
|
||||
|
|
@ -322,27 +326,29 @@ struct MQTTConfig: View {
|
|||
}
|
||||
|
||||
if let placemarks = placemarks, let placemark = placemarks.first {
|
||||
|
||||
let cc = locale.region?.identifier ?? "UNK"
|
||||
/// Country Topic unless you are US
|
||||
if placemark.isoCountryCode ?? "unknown" != "US" {
|
||||
let countryTopic = root + "/" + (placemark.isoCountryCode ?? "")
|
||||
if placemark.isoCountryCode ?? "unknown" != cc {
|
||||
let countryTopic = defaultTopic + "/" + (placemark.isoCountryCode ?? "")
|
||||
if !countryTopic.isEmpty {
|
||||
nearbyTopics.append(countryTopic)
|
||||
}
|
||||
}
|
||||
let stateTopic = root + "/" + (placemark.administrativeArea ?? "")
|
||||
let stateTopic = defaultTopic + "/" + (placemark.administrativeArea ?? "")
|
||||
if !stateTopic.isEmpty {
|
||||
nearbyTopics.append(stateTopic)
|
||||
}
|
||||
let countyTopic = root + "/" + (placemark.subAdministrativeArea?.lowercased().replacingOccurrences(of: " ", with: "") ?? "")
|
||||
let countyTopic = defaultTopic + "/" + (placemark.subAdministrativeArea?.lowercased().replacingOccurrences(of: " ", with: "") ?? "")
|
||||
if !countyTopic.isEmpty {
|
||||
nearbyTopics.append(countyTopic)
|
||||
}
|
||||
let cityTopic = root + "/" + (placemark.locality?.lowercased().replacingOccurrences(of: " ", with: "") ?? "")
|
||||
let cityTopic = defaultTopic + "/" + (placemark.locality?.lowercased().replacingOccurrences(of: " ", with: "") ?? "")
|
||||
if !cityTopic.isEmpty {
|
||||
nearbyTopics.append(cityTopic)
|
||||
}
|
||||
let neightborhoodTopic = root + "/" + (placemark.subLocality?.lowercased().replacingOccurrences(of: " ", with: "") ?? "")
|
||||
let neightborhoodTopic = defaultTopic + "/" + (placemark.subLocality?.lowercased()
|
||||
.replacingOccurrences(of: " ", with: "")
|
||||
.replacingOccurrences(of: "'", with: "") ?? "")
|
||||
if !neightborhoodTopic.isEmpty {
|
||||
nearbyTopics.append(neightborhoodTopic)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,13 +185,13 @@ struct TelemetryConfig: View {
|
|||
}
|
||||
}
|
||||
func setTelemetryValues() {
|
||||
self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 0)
|
||||
self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 0)
|
||||
self.deviceUpdateInterval = Int(node?.telemetryConfig?.deviceUpdateInterval ?? 900)
|
||||
self.environmentUpdateInterval = Int(node?.telemetryConfig?.environmentUpdateInterval ?? 900)
|
||||
self.environmentMeasurementEnabled = node?.telemetryConfig?.environmentMeasurementEnabled ?? false
|
||||
self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false
|
||||
self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false
|
||||
self.powerMeasurementEnabled = node?.telemetryConfig?.powerMeasurementEnabled ?? false
|
||||
self.powerUpdateInterval = Int(node?.telemetryConfig?.powerUpdateInterval ?? 0)
|
||||
self.powerUpdateInterval = Int(node?.telemetryConfig?.powerUpdateInterval ?? 900)
|
||||
self.powerScreenEnabled = node?.telemetryConfig?.powerScreenEnabled ?? false
|
||||
self.hasChanges = false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue