Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exchange Position Response Notifications #833

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Meshtastic/Helpers/MeshPackets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -712,10 +712,10 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
Notification(
id: ("notification.id.\(UUID().uuidString)"),
title: "Critically Low Battery!",
subtitle: "AKA \(telemetry.nodeTelemetry?.user?.shortName ?? "UNK")",
subtitle: "\(telemetry.nodeTelemetry?.user?.longName ?? "unknown".localized)",
content: "Time to charge your radio, there is \(telemetry.batteryLevel)% battery remaining.",
target: "nodes",
path: "meshtastic:///nodes?nodenum=\(telemetry.nodeTelemetry?.num ?? 0)"
path: "meshtastic:///nodes?nodenum=\(telemetry.nodeTelemetry?.num ?? 0)&detail=deviceMetricsLog"
)
]
manager.schedule()
Expand Down
4 changes: 2 additions & 2 deletions Meshtastic/MeshtasticAppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ class MeshtasticAppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificat
if let targetValue = userInfo["target"] as? String,
let deepLink = userInfo["path"] as? String,
let url = URL(string: deepLink) {
Logger.services.info("userNotificationCenter didReceiveResponse \(targetValue) \(deepLink)")
Logger.services.info("🔔 userNotificationCenter didReceiveResponse \(targetValue) \(deepLink)")
router?.route(url: url)
} else {
Logger.services.error("Failed to handle notification response: \(userInfo)")
Logger.services.error("💥 Failed to handle notification response: \(userInfo)")
}

completionHandler()
Expand Down
21 changes: 18 additions & 3 deletions Meshtastic/Persistence/UpdateCoreData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
fetchedNode[0].channel = Int32(packet.channel)
}

if let nodeInfoMessage = try? NodeInfo(serializedData: packet.decoded.payload) {
if let nodeInfoMessage = try? NodeInfo(serializedBytes: packet.decoded.payload) {

fetchedNode[0].hopsAway = Int32(nodeInfoMessage.hopsAway)
fetchedNode[0].favorite = nodeInfoMessage.isFavorite
Expand Down Expand Up @@ -290,7 +290,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)

do {

if let positionMessage = try? Position(serializedData: packet.decoded.payload) {
if let positionMessage = try? Position(serializedBytes: packet.decoded.payload) {

/// Don't save empty position packets from null island or apple park
if (positionMessage.longitudeI != 0 && positionMessage.latitudeI != 0) && (positionMessage.latitudeI != 373346000 && positionMessage.longitudeI != -1220090000) {
Expand Down Expand Up @@ -357,6 +357,21 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
do {
try context.save()
Logger.data.info("💾 [Position] Saved from Position App Packet For: \(fetchedNode[0].num.toHex(), privacy: .public)")
// Notification for position exchanges
if packet.to != 4294967295 {
let manager = LocalNotificationManager()
manager.notifications = [
Notification(
id: (UUID().uuidString),
title: "Position Exchange",
subtitle: "\(fetchedNode[0].user?.shortName ?? "unknown".localized)",
content: "\(fetchedNode[0].user?.longName ?? "unknown".localized) has shared their location with you.",
target: "nodes",
path: "meshtastic:///nodes?nodenum=\(packet.from)&detail=nodeMap"
)
]
manager.schedule()
}
} catch {
context.rollback()
let nsError = error as NSError
Expand All @@ -365,7 +380,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
}
} else {

if (try? NodeInfo(serializedData: packet.decoded.payload)) != nil {
if (try? NodeInfo(serializedBytes: packet.decoded.payload)) != nil {
upsertNodeInfoPacket(packet: packet, context: context)
} else {
Logger.data.error("💥 Empty POSITION_APP Packet: \((try? packet.jsonString()) ?? "JSON Decode Failure", privacy: .public)")
Expand Down
20 changes: 19 additions & 1 deletion Meshtastic/Router/NavigationState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ enum MapNavigationState: Hashable {
case waypoint(Int64)
}

// MARK: Node

struct NodeListNavigationState: Hashable {
let selectedNodeNum: Int64?
let details: NodeDetails?
}

enum NodeDetails: String, CaseIterable, Identifiable {
var id: String { self.rawValue }
case deviceMetricsLog
case nodeMap
case positionLog
case environmentMetricsLog
case traceRouteLog
case detectionSensorLog
case paxCounterLog
}

// MARK: Settings

enum SettingsNavigationState: String {
Expand Down Expand Up @@ -57,7 +75,7 @@ enum SettingsNavigationState: String {
enum NavigationState: Hashable {
case messages(MessagesNavigationState? = nil)
case bluetooth
case nodes(selectedNodeNum: Int64? = nil)
case nodes(NodeListNavigationState? = nil)
case map(MapNavigationState? = nil)
case settings(SettingsNavigationState? = nil)
}
Expand Down
7 changes: 5 additions & 2 deletions Meshtastic/Router/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,15 @@ class Router: ObservableObject {
route(to: .messages(state))
}

private func routeNodes(_ components: URLComponents) {
func routeNodes(_ components: URLComponents) {
let nodeId = components.queryItems?
.first(where: { $0.name == "nodenum" })?
.value
.flatMap(Int64.init)
route(to: .nodes(selectedNodeNum: nodeId))
let detail = components.queryItems?
.first(where: { $0.name == "detail" })?
.value
route(to: .nodes(NodeListNavigationState(selectedNodeNum: nodeId, details: detail != nil ? NodeDetails(rawValue: detail!) : nil)))
}

private func routeMap(_ components: URLComponents) {
Expand Down
Loading