Skip to content

Commit

Permalink
Merge branch 'main'
Browse files Browse the repository at this point in the history
#Conflicts:
#	Meshtastic/AppIntents/MessageChannelIntent.swift
#	Meshtastic/Views/Settings/Config/DeviceConfig.swift
  • Loading branch information
garthvh committed Oct 5, 2024
2 parents e1ec14d + 2a9ae23 commit 4a5c728
Show file tree
Hide file tree
Showing 28 changed files with 189 additions and 174 deletions.
35 changes: 1 addition & 34 deletions Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,6 @@
},
"%@%%" : {

},
"%@%% %@%%" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$@%% %2$@%%"
}
}
}
},
"%@°F" : {

Expand Down Expand Up @@ -1413,16 +1403,6 @@
},
"Bad" : {

},
"Bad Packets: %d %@%%" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Bad Packets: %1$d %2$@%%"
}
}
}
},
"Bandwidth" : {

Expand Down Expand Up @@ -14559,7 +14539,7 @@
"Message" : {

},
"Message content exceeds 228 bytes." : {
"Message content exceeds 200 bytes." : {

},
"Message Status Options" : {
Expand Down Expand Up @@ -16070,16 +16050,6 @@
},
"Override automatic OLED screen detection." : {

},
"Packets: Sent: %d Received: %d" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Packets: Sent: %1$d Received: %2$d"
}
}
}
},
"password" : {
"localizations" : {
Expand Down Expand Up @@ -22319,9 +22289,6 @@
}
}
}
},
"Uptime: %@" : {

},
"Use a PWM output (like the RAK Buzzer) for tunes instead of an on/off output. This will ignore the output, output duration and active settings and use the device config buzzer GPIO option instead." : {

Expand Down
8 changes: 4 additions & 4 deletions Meshtastic.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.5.5;
MARKETING_VERSION = 2.5.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
Expand Down Expand Up @@ -1720,7 +1720,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.5.5;
MARKETING_VERSION = 2.5.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
Expand Down Expand Up @@ -1752,7 +1752,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.5.5;
MARKETING_VERSION = 2.5.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -1785,7 +1785,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.5.5;
MARKETING_VERSION = 2.5.7;
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
6 changes: 3 additions & 3 deletions Meshtastic/AppIntents/MessageChannelIntent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ struct MessageChannelIntent: AppIntent {
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 messageData.count > 200 {
throw $messageContent.needsValueError("Message content exceeds 200 bytes.")
}

if !BLEManager.shared.sendMessage(message: messageContent, toUserNum: 0, channel: Int32(channelNumber), isEmoji: false, replyID: 0) {
Expand Down
1 change: 0 additions & 1 deletion Meshtastic/Enums/AppSettingsEnums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ enum MeshMapDistances: Double, CaseIterable, Identifiable {
case fifteenHundredMiles = 2414016
case twentyFiveHundredMiles = 4023360
case fiveThouandMiles = 8046720
case tenThousandMiles = 16093440
var id: Double { self.rawValue }
var description: String {
let distanceFormatter = MKDistanceFormatter()
Expand Down
16 changes: 15 additions & 1 deletion Meshtastic/Enums/RoutingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ enum RoutingError: Int, CaseIterable, Identifiable {
case notAuthorized = 33
case pkiFailed = 34
case pkiUnknownPubkey = 35
case adminBadSessionKey = 36
case adminPublicKeyUnauthorized = 37

var id: Int { self.rawValue }
var display: String {
Expand Down Expand Up @@ -57,6 +59,10 @@ enum RoutingError: Int, CaseIterable, Identifiable {
return "routing.pkifailed".localized
case .pkiUnknownPubkey:
return "routing.pkiunknownpubkey".localized
case .adminBadSessionKey:
return "routing.adminbadsessionkey".localized
case .adminPublicKeyUnauthorized:
return "routing.adminpublickeyunauthorized".localized
}
}
var color: Color {
Expand Down Expand Up @@ -97,7 +103,11 @@ enum RoutingError: Int, CaseIterable, Identifiable {
case .pkiFailed:
return true
case .pkiUnknownPubkey:
return false
return true
case .adminBadSessionKey:
return true
case .adminPublicKeyUnauthorized:
return true
}
}
func protoEnumValue() -> Routing.Error {
Expand Down Expand Up @@ -132,6 +142,10 @@ enum RoutingError: Int, CaseIterable, Identifiable {
return Routing.Error.pkiFailed
case .pkiUnknownPubkey:
return Routing.Error.pkiUnknownPubkey
case .adminBadSessionKey:
return Routing.Error.adminBadSessionKey
case .adminPublicKeyUnauthorized:
return Routing.Error.adminPublicKeyUnauthorized
}
}
}
27 changes: 27 additions & 0 deletions Meshtastic/Enums/TelemetryEnums.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,30 @@ enum Iaq: Int, CaseIterable, Identifiable {
return iaq
}
}


// Default of 0 is Client
enum MetricsTypes: Int, CaseIterable, Identifiable {

case device = 0
case environment = 1
case power = 2
case airQuality = 3
case stats = 4

var id: Int { self.rawValue }
var name: String {
switch self {
case .device:
return "Device Metrics"
case .environment:
return "Environment Metrics"
case .power:
return "Power Metrics"
case .airQuality:
return "Air Quality Metrics"
case .stats:
return "Stats"
}
}
}
1 change: 0 additions & 1 deletion Meshtastic/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,4 @@ extension String {
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return String(self[start ..< end])
}

}
17 changes: 14 additions & 3 deletions Meshtastic/Helpers/BLEManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,20 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
retained: decodedInfo.mqttClientProxyMessage.retained
)
mqttManager.mqttClientProxy?.publish(message)
} else if decodedInfo.payloadVariant == FromRadio.OneOf_PayloadVariant.clientNotification(decodedInfo.clientNotification) {
let manager = LocalNotificationManager()
manager.notifications = [
Notification(
id: UUID().uuidString,
title: "Firmware Notification",
subtitle: "\(decodedInfo.clientNotification.level)".capitalized,
content: decodedInfo.clientNotification.message,
target: "settings",
path: "meshtastic:///settings/debugLogs"
)
]
manager.schedule()
Logger.data.error("⚠️ Client Notification \((try? decodedInfo.clientNotification.jsonString()) ?? "JSON Decode Failure")")
}

switch decodedInfo.packet.decoded.portnum {
Expand Down Expand Up @@ -680,9 +694,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
do {
disconnectPeripheral(reconnect: false)
try container.restorePersistentStore(from: databasePath)
context.refreshAllObjects()
let request = MyInfoEntity.fetchRequest()
try context.fetch(request)
UserDefaults.preferredPeripheralNum = Int(myInfo?.myNodeNum ?? 0)
connectTo(peripheral: peripheral)
Logger.data.notice("🗂️ Restored Core data for /\(UserDefaults.preferredPeripheralNum, privacy: .public)")
Expand Down
51 changes: 22 additions & 29 deletions Meshtastic/Helpers/MeshPackets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
telemetry.numPacketsRxBad = Int32(truncatingIfNeeded: telemetryMessage.localStats.numPacketsRxBad)
telemetry.numOnlineNodes = Int32(truncatingIfNeeded: telemetryMessage.localStats.numOnlineNodes)
telemetry.numTotalNodes = Int32(truncatingIfNeeded: telemetryMessage.localStats.numTotalNodes)
telemetry.metricsType = 6
telemetry.metricsType = 4
Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.localStats.channelUtilization, privacy: .public) Airtime: \(telemetryMessage.localStats.airUtilTx, privacy: .public) Packets Sent: \(telemetryMessage.localStats.numPacketsTx, privacy: .public) Packets Received: \(telemetryMessage.localStats.numPacketsRx, privacy: .public) Bad Packets Received: \(telemetryMessage.localStats.numPacketsRxBad, privacy: .public) Nodes Online: \(telemetryMessage.localStats.numOnlineNodes, privacy: .public) of \(telemetryMessage.localStats.numTotalNodes, privacy: .public) nodes for Node: \(packet.from.toHex(), privacy: .public)")
}
telemetry.snr = packet.rxSnr
Expand All @@ -748,7 +748,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
}
try context.save()

Logger.data.info("💾 [TelemetryEntity] Saved for Node: \(packet.from.toHex())")
Logger.data.info("💾 [TelemetryEntity] of type \(MetricsTypes(rawValue: Int(telemetry.metricsType))?.name ?? "Unknown Metrics Type") Saved for Node: \(packet.from.toHex())")
if telemetry.metricsType == 0 {
// Connected Device Metrics
// ------------------------
Expand All @@ -769,9 +769,9 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
manager.schedule()
}
}
} else if telemetry.metricsType == 6 {
} else if telemetry.metricsType == 4 {
// Update our live activity if there is one running, not available on mac iOS >= 16.2
#if !targetEnvironment(macCatalyst)
#if canImport(ActivityKit)

let fifteenMinutesLater = Calendar.current.date(byAdding: .minute, value: (Int(15) ), to: Date())!
let date = Date.now...fifteenMinutesLater
Expand Down Expand Up @@ -827,7 +827,7 @@ func textMessageAppPacket(
}
}
let rangeTest = messageText?.contains(rangeTestRegex) ?? false && messageText?.starts(with: "seq ") ?? false

if !wantRangeTestPackets && rangeTest {
return
}
Expand All @@ -840,16 +840,13 @@ func textMessageAppPacket(
}
}
}

if messageText?.count ?? 0 > 0 {
MeshLogger.log("💬 \("mesh.log.textmessage.received".localized)")

let messageUsers = UserEntity.fetchRequest()
messageUsers.predicate = NSPredicate(format: "num IN %@", [packet.to, packet.from])

do {
let fetchedUsers = try context.fetch(messageUsers)

let newMessage = MessageEntity(context: context)
newMessage.messageId = Int64(packet.id)
if packet.rxTime > 0 {
Expand All @@ -863,60 +860,56 @@ func textMessageAppPacket(
newMessage.isEmoji = packet.decoded.emoji == 1
newMessage.channel = Int32(packet.channel)
newMessage.portNum = Int32(packet.decoded.portnum.rawValue)
if newMessage.toUser?.pkiEncrypted ?? false {
newMessage.pkiEncrypted = true
newMessage.publicKey = packet.publicKey
}
if packet.decoded.portnum == PortNum.detectionSensorApp {
if !UserDefaults.enableDetectionNotifications {
newMessage.read = true
}
}

if packet.decoded.replyID > 0 {
newMessage.replyID = Int64(packet.decoded.replyID)
}

if fetchedUsers.first(where: { $0.num == packet.to }) != nil && packet.to != Constants.maximumNodeNum {
if !storeForwardBroadcast {
newMessage.toUser = fetchedUsers.first(where: { $0.num == packet.to })
}
}

if fetchedUsers.first(where: { $0.num == packet.from }) != nil {
newMessage.fromUser = fetchedUsers.first(where: { $0.num == packet.from })

if !(newMessage.fromUser?.publicKey?.isEmpty ?? true) && newMessage.toUser != nil && packet.pkiEncrypted {
// We have a key and it is a PKC encrypted DM, check if it matches
if newMessage.fromUser?.publicKey != newMessage.publicKey {
newMessage.fromUser?.keyMatch = false
newMessage.fromUser?.newPublicKey = newMessage.publicKey
Logger.data.error("🔑 Key Mismatch origninal key: \(newMessage.fromUser?.publicKey?.base64EncodedString() ?? "No Key") new key: \(newMessage.fromUser?.newPublicKey?.base64EncodedString() ?? "No Key") ")
/// Set the public key for the message
if newMessage.fromUser?.pkiEncrypted ?? false {
newMessage.pkiEncrypted = true
newMessage.publicKey = packet.publicKey
}
/// Check for key mismatch
if let nodeKey = newMessage.fromUser?.publicKey {
if newMessage.toUser != nil && packet.pkiEncrypted && !packet.publicKey.isEmpty {
if nodeKey != newMessage.publicKey {
newMessage.fromUser?.keyMatch = false
newMessage.fromUser?.newPublicKey = newMessage.publicKey
let nodeKey = String(nodeKey.base64EncodedString()).prefix(8)
let messageKey = String(newMessage.publicKey?.base64EncodedString() ?? "No Key").prefix(8)
Logger.data.error("🔑 Key mismatch original key: \(nodeKey, privacy: .public) . . . new key: \(messageKey, privacy: .public) . . .")
}
}
} else {
} else if packet.pkiEncrypted {
/// We have no key, set it if it is not empty
if !packet.publicKey.isEmpty {
newMessage.fromUser?.pkiEncrypted = true
newMessage.fromUser?.publicKey = packet.publicKey
}
}

if packet.rxTime > 0 {
newMessage.fromUser?.userNode?.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
} else {
newMessage.fromUser?.userNode?.lastHeard = Date()
}
}

newMessage.messagePayload = messageText
newMessage.messagePayloadMarkdown = generateMessageMarkdown(message: messageText!)

if packet.to != Constants.maximumNodeNum && newMessage.fromUser != nil {
newMessage.fromUser?.lastMessage = Date()
}

var messageSaved = false

do {
try context.save()
Logger.data.info("💾 Saved a new message for \(newMessage.messageId)")
Expand Down
Loading

0 comments on commit 4a5c728

Please sign in to comment.