-
-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #866 from meshtastic/AppIntents
App intents
- Loading branch information
Showing
10 changed files
with
326 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// AppIntentErrors.swift | ||
// Meshtastic | ||
// | ||
// Created by Benjamin Faershtein on 8/11/24. | ||
// | ||
|
||
import Foundation | ||
|
||
class AppIntentErrors { | ||
enum AppIntentError: Swift.Error, CustomLocalizedStringResourceConvertible { | ||
case notConnected | ||
case message(_ message: String) | ||
|
||
var localizedStringResource: LocalizedStringResource { | ||
switch self { | ||
case let .message(message): return "Error: \(message)" | ||
case .notConnected: return "No Connected Node" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// MessageChannelIntent.swift | ||
// Meshtastic | ||
// | ||
// Created by Benjamin Faershtein on 8/9/24. | ||
// | ||
|
||
import Foundation | ||
import AppIntents | ||
|
||
struct MessageChannelIntent: AppIntent { | ||
static var title: LocalizedStringResource = "Send a channel message" | ||
|
||
static var description: IntentDescription = "Send a message to a certain meshtastic channel" | ||
|
||
@Parameter(title: "Message") | ||
var messageContent: String | ||
|
||
@Parameter(title: "Channel",controlStyle: .stepper, inclusiveRange: (lowerBound: 0, upperBound: 7)) | ||
var channelNumber: Int | ||
|
||
|
||
static var parameterSummary: some ParameterSummary { | ||
Summary("Send \(\.$messageContent) to \(\.$channelNumber)") | ||
} | ||
func perform() async throws -> some IntentResult { | ||
if (!BLEManager.shared.isConnected){ | ||
throw AppIntentErrors.AppIntentError.notConnected | ||
} | ||
|
||
// Check if channel number is between 1 and 7 | ||
guard (0...7).contains(channelNumber) else { | ||
throw $channelNumber.needsValueError("Channel number must be between 0 and 7.") | ||
} | ||
|
||
// Convert messageContent to data and check its length | ||
guard let messageData = messageContent.data(using: .utf8) else { | ||
throw AppIntentErrors.AppIntentError.message("Failed to encode message content") | ||
} | ||
|
||
if messageData.count > 228 { | ||
throw $messageContent.needsValueError("Message content exceeds 228 bytes.") | ||
} | ||
|
||
if(!BLEManager.shared.sendMessage(message: messageContent, toUserNum: 0, channel: Int32(channelNumber), isEmoji: false, replyID: 0)){ | ||
throw AppIntentErrors.AppIntentError.message("Failed to send message") | ||
} | ||
|
||
return .result() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// NodePositionIntent.swift | ||
// Meshtastic | ||
// | ||
// Created by Benjamin Faershtein on 8/10/24. | ||
// | ||
|
||
import Foundation | ||
import AppIntents | ||
import CoreLocation | ||
import CoreData | ||
|
||
struct NodePositionIntent: AppIntent { | ||
|
||
@Parameter(title: "Node Number") | ||
var nodeNum: Int | ||
|
||
static var title: LocalizedStringResource = "Get Node Position" | ||
static var description: IntentDescription = "Fetch the latest position of a cetain node" | ||
|
||
|
||
func perform() async throws -> some IntentResult & ReturnsValue<CLPlacemark> { | ||
if (!BLEManager.shared.isConnected) { | ||
throw AppIntentErrors.AppIntentError.notConnected | ||
} | ||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "NodeInfoEntity") | ||
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) | ||
do { | ||
guard let fetchedNode = try PersistenceController.shared.container.viewContext.fetch(fetchNodeInfoRequest) as? [NodeInfoEntity], fetchedNode.count == 1 else { | ||
throw $nodeNum.needsValueError("Could not find node") | ||
} | ||
|
||
let nodeInfo = fetchedNode[0] | ||
if let latitude = nodeInfo.latestPosition?.coordinate.latitude, | ||
let longitude = nodeInfo.latestPosition?.coordinate.longitude { | ||
let nodeLocation = CLLocation(latitude: latitude, longitude: longitude) | ||
|
||
// Reverse geocode the CLLocation to get a CLPlacemark | ||
let geocoder = CLGeocoder() | ||
let placemarks = try await geocoder.reverseGeocodeLocation(nodeLocation) | ||
|
||
if let placemark = placemarks.first { | ||
return .result(value: placemark) | ||
} else { | ||
throw AppIntentErrors.AppIntentError.message("Error Reverse Geocoding Location") | ||
} | ||
} else { | ||
throw AppIntentErrors.AppIntentError.message("Node does not have positions") | ||
} | ||
} catch { | ||
throw AppIntentErrors.AppIntentError.message("Fetch Failure") | ||
} | ||
} | ||
|
||
} | ||
|
Oops, something went wrong.