mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #898 from RCGV1/AppIntents
Added Shortcuts provider and Shut Down, Reboot, and Factory Reset Int…
This commit is contained in:
commit
64fcb58955
10 changed files with 226 additions and 12 deletions
|
|
@ -1166,6 +1166,9 @@
|
|||
},
|
||||
"Are you sure you want to delete this message?" : {
|
||||
|
||||
},
|
||||
"Are you sure you want to factory reset the node?" : {
|
||||
|
||||
},
|
||||
"are.you.sure" : {
|
||||
"localizations" : {
|
||||
|
|
@ -6325,7 +6328,7 @@
|
|||
"Direct Message Help" : {
|
||||
|
||||
},
|
||||
"Direct messages are using the new public key infrastructure for encryption. Reguires firmware version 2.5 or greater." : {
|
||||
"Direct messages are using the new public key infrastructure for encryption. Requires firmware version 2.5 or greater." : {
|
||||
|
||||
},
|
||||
"Direct messages are using the shared key for the channel." : {
|
||||
|
|
@ -7209,6 +7212,9 @@
|
|||
},
|
||||
"Factory Reset" : {
|
||||
|
||||
},
|
||||
"Factory Reset Node" : {
|
||||
|
||||
},
|
||||
"Factory reset your device and app? " : {
|
||||
|
||||
|
|
@ -7227,12 +7233,12 @@
|
|||
},
|
||||
"Favorites" : {
|
||||
|
||||
},
|
||||
"Fetch the latest position of a cetain node" : {
|
||||
|
||||
},
|
||||
"Favorites and nodes with recent messages show up at the top of the contact list." : {
|
||||
|
||||
|
||||
},
|
||||
"Fetch the latest position of a cetain node" : {
|
||||
|
||||
},
|
||||
"Fifteen Minutes" : {
|
||||
|
||||
|
|
@ -14563,11 +14569,15 @@
|
|||
},
|
||||
"Message" : {
|
||||
|
||||
},
|
||||
"Message Channel" : {
|
||||
|
||||
},
|
||||
"Message content exceeds 228 bytes." : {
|
||||
|
||||
},
|
||||
"Message Status Options" : {
|
||||
|
||||
|
||||
},
|
||||
"message.details" : {
|
||||
"localizations" : {
|
||||
|
|
@ -16319,6 +16329,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Perform a factory reset on the node you are connected to" : {
|
||||
|
||||
},
|
||||
"phone.gps" : {
|
||||
"localizations" : {
|
||||
|
|
@ -17024,6 +17037,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Reboot Node?" : {
|
||||
|
||||
},
|
||||
"reboot.node" : {
|
||||
"localizations" : {
|
||||
|
|
@ -17389,6 +17405,12 @@
|
|||
},
|
||||
"Reset NodeDB" : {
|
||||
|
||||
},
|
||||
"Restart Node" : {
|
||||
|
||||
},
|
||||
"Restart to the node you are connected to" : {
|
||||
|
||||
},
|
||||
"restore" : {
|
||||
|
||||
|
|
@ -19131,13 +19153,16 @@
|
|||
"Send" : {
|
||||
|
||||
},
|
||||
"Send a channel message" : {
|
||||
"Send a Channel Message" : {
|
||||
|
||||
},
|
||||
"Send a message to a certain meshtastic channel" : {
|
||||
|
||||
},
|
||||
"Send a waypoint" : {
|
||||
"Send a shutdown to the node you are connected to" : {
|
||||
|
||||
},
|
||||
"Send a Waypoint" : {
|
||||
|
||||
},
|
||||
"Send ASCII bell with alert message. Useful for triggering external notification on bell." : {
|
||||
|
|
@ -19876,6 +19901,12 @@
|
|||
},
|
||||
"Show Weather" : {
|
||||
|
||||
},
|
||||
"Shut Down Node" : {
|
||||
|
||||
},
|
||||
"Shut Down Node?" : {
|
||||
|
||||
},
|
||||
"Shutdown Node?" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@
|
|||
BCB613832C672A2600485544 /* MessageChannelIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613822C672A2600485544 /* MessageChannelIntent.swift */; };
|
||||
BCB613852C68703800485544 /* NodePositionIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613842C68703800485544 /* NodePositionIntent.swift */; };
|
||||
BCB613872C69A0FB00485544 /* AppIntentErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613862C69A0FB00485544 /* AppIntentErrors.swift */; };
|
||||
BCE2D3C32C7ADF42008E6199 /* ShutDownNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCE2D3C22C7ADF42008E6199 /* ShutDownNodeIntent.swift */; };
|
||||
BCE2D3C52C7AE369008E6199 /* RestartNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCE2D3C42C7AE369008E6199 /* RestartNodeIntent.swift */; };
|
||||
BCE2D3C72C7B0D0A008E6199 /* ShortcutsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCE2D3C62C7B0D0A008E6199 /* ShortcutsProvider.swift */; };
|
||||
BCE2D3C92C7C377F008E6199 /* FactoryResetNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCE2D3C82C7C377F008E6199 /* FactoryResetNodeIntent.swift */; };
|
||||
C9697FA527933B8C00250207 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = C9697FA427933B8C00250207 /* SQLite */; };
|
||||
D93068D32B8129510066FBC8 /* MessageContextMenuItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D22B8129510066FBC8 /* MessageContextMenuItems.swift */; };
|
||||
D93068D52B812B700066FBC8 /* MessageDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D42B812B700066FBC8 /* MessageDestination.swift */; };
|
||||
|
|
@ -275,6 +279,10 @@
|
|||
BCB613822C672A2600485544 /* MessageChannelIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageChannelIntent.swift; sourceTree = "<group>"; };
|
||||
BCB613842C68703800485544 /* NodePositionIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodePositionIntent.swift; sourceTree = "<group>"; };
|
||||
BCB613862C69A0FB00485544 /* AppIntentErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntentErrors.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C22C7ADF42008E6199 /* ShutDownNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShutDownNodeIntent.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C42C7AE369008E6199 /* RestartNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestartNodeIntent.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C62C7B0D0A008E6199 /* ShortcutsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsProvider.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C82C7C377F008E6199 /* FactoryResetNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FactoryResetNodeIntent.swift; sourceTree = "<group>"; };
|
||||
D93068D22B8129510066FBC8 /* MessageContextMenuItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageContextMenuItems.swift; sourceTree = "<group>"; };
|
||||
D93068D42B812B700066FBC8 /* MessageDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageDestination.swift; sourceTree = "<group>"; };
|
||||
D93068D62B8146690066FBC8 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -573,6 +581,10 @@
|
|||
BCB613822C672A2600485544 /* MessageChannelIntent.swift */,
|
||||
BCB613842C68703800485544 /* NodePositionIntent.swift */,
|
||||
BCB613862C69A0FB00485544 /* AppIntentErrors.swift */,
|
||||
BCE2D3C22C7ADF42008E6199 /* ShutDownNodeIntent.swift */,
|
||||
BCE2D3C42C7AE369008E6199 /* RestartNodeIntent.swift */,
|
||||
BCE2D3C82C7C377F008E6199 /* FactoryResetNodeIntent.swift */,
|
||||
BCE2D3C62C7B0D0A008E6199 /* ShortcutsProvider.swift */,
|
||||
);
|
||||
path = AppIntents;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1257,6 +1269,7 @@
|
|||
25F26B1F2C2F611300C9CD9D /* AppData.swift in Sources */,
|
||||
25F26B1E2C2F610D00C9CD9D /* Logger.swift in Sources */,
|
||||
259792252C2F114500AD1659 /* ChannelEntityExtension.swift in Sources */,
|
||||
BCE2D3C52C7AE369008E6199 /* RestartNodeIntent.swift in Sources */,
|
||||
259792262C2F114500AD1659 /* PositionEntityExtension.swift in Sources */,
|
||||
259792272C2F114500AD1659 /* TraceRouteEntityExtension.swift in Sources */,
|
||||
DDDB444829F8A9C900EE2349 /* String.swift in Sources */,
|
||||
|
|
@ -1361,6 +1374,7 @@
|
|||
D93068D32B8129510066FBC8 /* MessageContextMenuItems.swift in Sources */,
|
||||
DD8EBF43285058FA00426DCA /* DisplayConfig.swift in Sources */,
|
||||
DD964FC42974767D007C176F /* MapViewFitExtension.swift in Sources */,
|
||||
BCE2D3C72C7B0D0A008E6199 /* ShortcutsProvider.swift in Sources */,
|
||||
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,
|
||||
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */,
|
||||
DD2553572855B02500E55709 /* LoRaConfig.swift in Sources */,
|
||||
|
|
@ -1421,6 +1435,7 @@
|
|||
BCB613872C69A0FB00485544 /* AppIntentErrors.swift in Sources */,
|
||||
DD73FD1128750779000852D6 /* PositionLog.swift in Sources */,
|
||||
DD15E4F52B8BFC8E00654F61 /* PaxCounterLog.swift in Sources */,
|
||||
BCE2D3C32C7ADF42008E6199 /* ShutDownNodeIntent.swift in Sources */,
|
||||
25F5D5C22C3F6E4B008036E3 /* AppState.swift in Sources */,
|
||||
DD3CC6C028E7A60700FA9159 /* MessagingEnums.swift in Sources */,
|
||||
DD6F657B2C6EC2900053C113 /* LockLegend.swift in Sources */,
|
||||
|
|
@ -1436,6 +1451,7 @@
|
|||
DDDB26442AAC0206003AFCB7 /* NodeDetail.swift in Sources */,
|
||||
DD77093F2AA1B146007A8BF0 /* UIColor.swift in Sources */,
|
||||
DDF6B2482A9AEBF500BA6931 /* StoreForwardConfig.swift in Sources */,
|
||||
BCE2D3C92C7C377F008E6199 /* FactoryResetNodeIntent.swift in Sources */,
|
||||
DD8169F9271F1A6100F4AB02 /* MeshLogger.swift in Sources */,
|
||||
DD93800B2BA3F968008BEC06 /* NodeMapContent.swift in Sources */,
|
||||
DD41582A28585C32009B0E59 /* RangeTestConfig.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
class AppIntentErrors {
|
||||
enum AppIntentError: Swift.Error, CustomLocalizedStringResourceConvertible {
|
||||
|
|
@ -14,8 +15,12 @@ class AppIntentErrors {
|
|||
|
||||
var localizedStringResource: LocalizedStringResource {
|
||||
switch self {
|
||||
case let .message(message): return "Error: \(message)"
|
||||
case .notConnected: return "No Connected Node"
|
||||
case let .message(message):
|
||||
Logger.services.error("App Intent: \(message)")
|
||||
return "Error: \(message)"
|
||||
case .notConnected:
|
||||
Logger.services.error("App Intent: No Connected Node")
|
||||
return "No Connected Node"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
41
Meshtastic/AppIntents/FactoryResetNodeIntent.swift
Normal file
41
Meshtastic/AppIntents/FactoryResetNodeIntent.swift
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// FactoryResetNodeIntent.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 8/25/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppIntents
|
||||
|
||||
struct FactoryResetNodeIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Factory Reset Node"
|
||||
static var description: IntentDescription = "Perform a factory reset on the node you are connected to"
|
||||
|
||||
func perform() async throws -> some IntentResult {
|
||||
// Request user confirmation before performing the factory reset
|
||||
try await requestConfirmation(result: .result(dialog: "Are you sure you want to factory reset the node?"),confirmationActionName: ConfirmationActionName
|
||||
.custom(acceptLabel: "Factory Reset", acceptAlternatives: [], denyLabel: "Cancel", denyAlternatives: [], destructive: true))
|
||||
|
||||
// Ensure the node is connected
|
||||
if !BLEManager.shared.isConnected {
|
||||
throw AppIntentErrors.AppIntentError.notConnected
|
||||
}
|
||||
|
||||
// Safely unwrap the connected node information
|
||||
if let connectedPeripheralNum = BLEManager.shared.connectedPeripheral?.num,
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheralNum, context: PersistenceController.shared.container.viewContext),
|
||||
let fromUser = connectedNode.user,
|
||||
let toUser = connectedNode.user {
|
||||
|
||||
// Attempt to send a factory reset command, throw an error if it fails
|
||||
if !BLEManager.shared.sendFactoryReset(fromUser: fromUser, toUser: toUser) {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to perform factory reset")
|
||||
}
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to retrieve connected node or required data")
|
||||
}
|
||||
//
|
||||
return .result()
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import Foundation
|
|||
import AppIntents
|
||||
|
||||
struct MessageChannelIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Send a channel message"
|
||||
static var title: LocalizedStringResource = "Send a Channel Message"
|
||||
|
||||
static var description: IntentDescription = "Send a message to a certain meshtastic channel"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct NodePositionIntent: AppIntent {
|
|||
}
|
||||
|
||||
let nodeInfo = fetchedNode[0]
|
||||
nodeInfo.latestEnvironmentMetrics?.batteryLevel
|
||||
if let latitude = nodeInfo.latestPosition?.coordinate.latitude,
|
||||
let longitude = nodeInfo.latestPosition?.coordinate.longitude {
|
||||
let nodeLocation = CLLocation(latitude: latitude, longitude: longitude)
|
||||
|
|
|
|||
42
Meshtastic/AppIntents/RestartNodeIntent.swift
Normal file
42
Meshtastic/AppIntents/RestartNodeIntent.swift
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// RestartNodeIntent.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 8/24/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppIntents
|
||||
|
||||
struct RestartNodeIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Restart Node"
|
||||
|
||||
static var description: IntentDescription = "Restart to the node you are connected to"
|
||||
|
||||
|
||||
func perform() async throws -> some IntentResult {
|
||||
|
||||
try await requestConfirmation(result: .result(dialog: "Reboot Node?"))
|
||||
|
||||
if !BLEManager.shared.isConnected {
|
||||
throw AppIntentErrors.AppIntentError.notConnected
|
||||
}
|
||||
// Safely unwrap the connectedNode using if let
|
||||
if let connectedPeripheralNum = BLEManager.shared.connectedPeripheral?.num,
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheralNum, context: PersistenceController.shared.container.viewContext),
|
||||
let fromUser = connectedNode.user,
|
||||
let toUser = connectedNode.user,
|
||||
let adminIndex = connectedNode.myInfo?.adminIndex {
|
||||
|
||||
// Attempt to send shutdown, throw an error if it fails
|
||||
if !BLEManager.shared.sendReboot(fromUser: fromUser, toUser: toUser, adminIndex: adminIndex) {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to restart")
|
||||
}
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to retrieve connected node or required data")
|
||||
}
|
||||
|
||||
return .result()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ import MeshtasticProtobufs
|
|||
|
||||
struct SendWaypointIntent: AppIntent {
|
||||
|
||||
static var title = LocalizedStringResource("Send a waypoint")
|
||||
static var title = LocalizedStringResource("Send a Waypoint")
|
||||
|
||||
@Parameter(title: "Name", default: "Dropped Pin")
|
||||
var nameParameter: String?
|
||||
|
|
|
|||
37
Meshtastic/AppIntents/ShortcutsProvider.swift
Normal file
37
Meshtastic/AppIntents/ShortcutsProvider.swift
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// ShortcutsProvider.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 8/24/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppIntents
|
||||
|
||||
struct ShortcutsProvider: AppShortcutsProvider {
|
||||
static var appShortcuts: [AppShortcut] {
|
||||
AppShortcut(intent: ShutDownNodeIntent(),
|
||||
phrases: ["Shut down node in \(.applicationName)",
|
||||
"Turn off node in \(.applicationName)",
|
||||
"Power down node in \(.applicationName)",
|
||||
"Deactivate node in \(.applicationName)"],
|
||||
shortTitle: "Shut Down Node",
|
||||
systemImageName: "power")
|
||||
|
||||
AppShortcut(intent: RestartNodeIntent(),
|
||||
phrases: ["Restart node in \(.applicationName)",
|
||||
"Reboot node in \(.applicationName)",
|
||||
"Reset node in \(.applicationName)",
|
||||
"Start node again in \(.applicationName)"],
|
||||
shortTitle: "Restart Node",
|
||||
systemImageName: "arrow.circlepath")
|
||||
|
||||
AppShortcut(intent: MessageChannelIntent(),
|
||||
phrases: ["Message channel in \(.applicationName)",],
|
||||
shortTitle: "Message Channel",
|
||||
systemImageName: "message")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
41
Meshtastic/AppIntents/ShutDownNodeIntent.swift
Normal file
41
Meshtastic/AppIntents/ShutDownNodeIntent.swift
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// ShutDownNodeIntent.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 8/24/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppIntents
|
||||
|
||||
struct ShutDownNodeIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Shut Down Node"
|
||||
|
||||
static var description: IntentDescription = "Send a shutdown to the node you are connected to"
|
||||
|
||||
|
||||
func perform() async throws -> some IntentResult {
|
||||
try await requestConfirmation(result: .result(dialog: "Shut Down Node?"))
|
||||
|
||||
if !BLEManager.shared.isConnected {
|
||||
throw AppIntentErrors.AppIntentError.notConnected
|
||||
}
|
||||
|
||||
// Safely unwrap the connectedNode using if let
|
||||
if let connectedPeripheralNum = BLEManager.shared.connectedPeripheral?.num,
|
||||
let connectedNode = getNodeInfo(id: connectedPeripheralNum, context: PersistenceController.shared.container.viewContext),
|
||||
let fromUser = connectedNode.user,
|
||||
let toUser = connectedNode.user,
|
||||
let adminIndex = connectedNode.myInfo?.adminIndex {
|
||||
|
||||
// Attempt to send shutdown, throw an error if it fails
|
||||
if !BLEManager.shared.sendShutdown(fromUser: fromUser, toUser: toUser, adminIndex: adminIndex) {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to shut down")
|
||||
}
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to retrieve connected node or required data")
|
||||
}
|
||||
|
||||
return .result()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue