mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Update widgets with local device metrics
This commit is contained in:
parent
00d9f7b474
commit
a07f0f6817
4 changed files with 37 additions and 15 deletions
|
|
@ -8,6 +8,9 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
import SwiftUI
|
||||
#if canImport(ActivityKit)
|
||||
import ActivityKit
|
||||
#endif
|
||||
|
||||
func generateMessageMarkdown (message: String) -> String {
|
||||
|
||||
|
|
@ -635,6 +638,9 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
|
|||
if connectedNode != Int64(packet.from) {
|
||||
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.telemetry.received %@", comment: "Telemetry received for: %@"), String(packet.from))
|
||||
MeshLogger.log("📈 \(logString)")
|
||||
} else {
|
||||
// If it is the connected node
|
||||
|
||||
}
|
||||
|
||||
let telemetry = TelemetryEntity(context: context)
|
||||
|
|
@ -674,6 +680,24 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
|
|||
// Only log telemetry from the mesh not the connected device
|
||||
if connectedNode != Int64(packet.from) {
|
||||
print("💾 Telemetry Saved for Node: \(packet.from)")
|
||||
} else if telemetry.metricsType == 0 {
|
||||
if #available(iOS 16.2, *) {
|
||||
var future = Calendar.current.date(byAdding: .minute, value: (Int(0) ), to: Date())!
|
||||
future = Calendar.current.date(byAdding: .second, value: (Int(60) ), to: future)!
|
||||
let date = Date.now...future
|
||||
let updatedMeshStatus = MeshActivityAttributes.MyActivityStatus(timerRange: date, connected: true, channelUtilization: telemetry.channelUtilization, airtime: telemetry.airUtilTx, batteryLevel: UInt32(telemetry.batteryLevel))
|
||||
|
||||
let alertConfiguration = AlertConfiguration(title: "Mesh activity update", body: "Updated Metrics Data.", sound: .default)
|
||||
let updatedContent = ActivityContent(state: updatedMeshStatus, staleDate: nil)
|
||||
print("Update live activity.")
|
||||
|
||||
let stuff = Activity<MeshActivityAttributes>.activities.first(where: { $0.attributes.nodeNum == connectedNode })
|
||||
if stuff != nil {
|
||||
Task {
|
||||
await stuff?.update(updatedContent, alertConfiguration: alertConfiguration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
context.rollback()
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ struct Connect: View {
|
|||
Text("Max Channels: \(String(node?.myInfo?.maxChannels ?? 0))")
|
||||
Text("Bitrate: \(String(format: "%.2f", node?.myInfo?.bitrate ?? 0.00))")
|
||||
Text("BLE RSSI: \(bleManager.connectedPeripheral.rssi)")
|
||||
|
||||
}
|
||||
}
|
||||
if isUnsetRegion {
|
||||
|
|
@ -316,11 +315,11 @@ func startNodeActivity() {
|
|||
|
||||
let mostRecent = node?.telemetries?.lastObject as! TelemetryEntity
|
||||
|
||||
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName ?? "unknown", connected: true, channelUtilization: mostRecent.channelUtilization, airtime: mostRecent.airUtilTx, batteryLevel: UInt32(mostRecent.batteryLevel))
|
||||
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName ?? "unknown")
|
||||
|
||||
let future = Date(timeIntervalSinceNow: Double(timerSeconds))
|
||||
|
||||
let initialContentState = MeshActivityAttributes.ContentState(timerRange: Date.now...future)
|
||||
let initialContentState = MeshActivityAttributes.ContentState(timerRange: Date.now...future, connected: true, channelUtilization: mostRecent.channelUtilization, airtime: mostRecent.airUtilTx, batteryLevel: UInt32(mostRecent.batteryLevel))
|
||||
|
||||
let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 2, to: Date())!)
|
||||
|
||||
|
|
@ -328,7 +327,6 @@ func startNodeActivity() {
|
|||
let myActivity = try Activity<MeshActivityAttributes>.request(attributes: activityAttributes, content: activityContent,
|
||||
pushType: nil)
|
||||
print(" Requested MyActivity live activity. ID: \(myActivity.id)")
|
||||
postNotification()
|
||||
} catch let error {
|
||||
print("Error requesting live activity: \(error.localizedDescription)")
|
||||
}
|
||||
|
|
@ -352,7 +350,7 @@ func endActivity() {
|
|||
|
||||
#if os(iOS)
|
||||
func postNotification() {
|
||||
let timerSeconds = 300
|
||||
let timerSeconds = 60
|
||||
let content = UNMutableNotificationContent()
|
||||
content.title = "Mesh Live Activity Over"
|
||||
content.body = "Your timed mesh live activity is over."
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ struct MeshActivityAttributes: ActivityAttributes {
|
|||
public struct ContentState: Codable, Hashable {
|
||||
// Dynamic stateful properties about your activity go here!
|
||||
var timerRange: ClosedRange<Date>
|
||||
var connected: Bool
|
||||
var channelUtilization: Float
|
||||
var airtime: Float
|
||||
var batteryLevel: UInt32
|
||||
}
|
||||
|
||||
// Fixed non-changing properties about your activity go here!
|
||||
var nodeNum: Int
|
||||
var name: String
|
||||
var connected: Bool
|
||||
var channelUtilization: Float
|
||||
var airtime: Float
|
||||
var batteryLevel: UInt32
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ struct WidgetsLiveActivity: Widget {
|
|||
var body: some WidgetConfiguration {
|
||||
|
||||
ActivityConfiguration(for: MeshActivityAttributes.self) { context in
|
||||
LiveActivityView(nodeName: context.attributes.name, connected: context.attributes.connected, channelUtilization: context.attributes.channelUtilization, airtime: context.attributes.airtime, batteryLevel: context.attributes.batteryLevel, timerRange: context.state.timerRange)
|
||||
LiveActivityView(nodeName: context.attributes.name, connected: context.state.connected, channelUtilization: context.state.channelUtilization, airtime: context.state.airtime, batteryLevel: context.state.batteryLevel, timerRange: context.state.timerRange)
|
||||
.widgetURL(URL(string: "meshtastic://node/\(context.attributes.name)"))
|
||||
|
||||
} dynamicIsland: { context in
|
||||
DynamicIsland {
|
||||
DynamicIslandExpandedRegion(.leading) {
|
||||
NodeInfoView(nodeName: context.attributes.name, connected: context.attributes.connected, channelUtilization: context.attributes.channelUtilization, airtime: context.attributes.airtime, batteryLevel: context.attributes.batteryLevel)
|
||||
NodeInfoView(nodeName: context.attributes.name, connected: context.state.connected, channelUtilization: context.state.channelUtilization, airtime: context.state.airtime, batteryLevel: context.state.batteryLevel)
|
||||
.tint(Color("LightIndigo"))
|
||||
.padding(.top)
|
||||
}
|
||||
|
|
@ -65,9 +65,9 @@ struct WidgetsLiveActivity: Widget {
|
|||
|
||||
@available(iOS 16.2, *)
|
||||
struct WidgetsLiveActivity_Previews: PreviewProvider {
|
||||
static let attributes = MeshActivityAttributes(nodeNum: 123456789, name: "Meshtastic 8E6G", connected: true, channelUtilization: 0.24, airtime: 0.87, batteryLevel: 39)
|
||||
static let attributes = MeshActivityAttributes(nodeNum: 123456789, name: "Meshtastic 8E6G")
|
||||
static let state = MeshActivityAttributes.ContentState(
|
||||
timerRange: Date.now...Date(timeIntervalSinceNow: 3600))
|
||||
timerRange: Date.now...Date(timeIntervalSinceNow: 3600), connected: true, channelUtilization: 25.84, airtime: 10.01, batteryLevel: 39)
|
||||
|
||||
static var previews: some View {
|
||||
attributes
|
||||
|
|
@ -168,14 +168,14 @@ struct TimerView: View {
|
|||
.monospacedDigit()
|
||||
.multilineTextAlignment(.trailing)
|
||||
.frame(width: 80)
|
||||
.font(.title3)
|
||||
.font(.callout)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundStyle(.tint)
|
||||
Image(systemName: "timer")
|
||||
.resizable()
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(width: 30, height: 30)
|
||||
.padding(.trailing)
|
||||
.padding(.trailing, 7)
|
||||
.opacity(isLuminanceReduced ? 0.5 : 1.0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue