Skip to content

Commit bc39cbd

Browse files
garthvhMGJ520compumikeRCGV1alvarosamudio
authored
Make BLE Transport an actor to fix background discovery crashes (#1554)
* Bump version * update the translations (#1540) update the translations * Don't alert (with sound: .default) when updating Live Activity (#1536) * Fix adding channels (#1532) * Full translation into Spanish (#1529) * tapback with any emoji (#1538) * Call clearStaleNodes at start of sendWantConfig (#1535) * NFC Tag contact (#1537) * Accessorymanager background discovery (#1542) * Don't add new BLE devices to the device list in the backgournd * Bump version * Update Meshtastic/MeshtasticApp.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update Meshtastic/MeshtasticApp.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Revert "Full translation into Spanish (#1529)" (#1543) This reverts commit f25fdfb. * Revert "update the translations (#1540)" (#1544) This reverts commit cb2fd8c. * Revert "NFC Tag contact (#1537)" (#1545) This reverts commit 5c22b8b. * Update Meshtastic/Views/Messages/TapbackInputView.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update Meshtastic/Helpers/EmojiOnlyTextField.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Revert "Accessorymanager background discovery (#1542)" (#1553) This reverts commit 487f24b. * Make BLE Transport an actor to fix background discovery crashes * Update protobufs * Protobufs * Remove UI Kit code, clean up waypoint form emoji picker * Remove redundant nested Task in tapback emoji handler (#1552) * Initial plan * Remove nested Task block in tapback handler Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Delete empty file * Handle nil for emoji keyboard type extension * Remove UI kit method from waypoint form emoji picker * Remove UI kit emoji picker from tapback * Update Meshtastic/Accessory/Transports/Bluetooth Low Energy/BLETransport.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Throw too many retries error again, remove return --------- Co-authored-by: MGJ <62177301+MGJ520@users.noreply.github.com> Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu> Co-authored-by: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Co-authored-by: Alvaro Samudio <alvarosamudio@protonmail.com> Co-authored-by: Mathew Kamkar <578302+matkam@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ben Meadors <benmmeadors@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
1 parent b30dc86 commit bc39cbd

File tree

23 files changed

+499
-140
lines changed

23 files changed

+499
-140
lines changed

Localizable.xcstrings

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14315,6 +14315,7 @@
1431514315
}
1431614316
},
1431714317
"Favorited and ignored nodes are always retained. Nodes without PKC keys are cleared from the app database on the schedule set by the user, nodes with PKC keys are cleared only if the interval is set to 7 days or longer. This feature only purges nodes from the app that are not stored in the device node database." : {
14318+
"extractionState" : "stale",
1431814319
"localizations" : {
1431914320
"de" : {
1432014321
"stringUnit" : {
@@ -14335,6 +14336,9 @@
1433514336
}
1433614337
}
1433714338
}
14339+
},
14340+
"Favorited and ignored nodes are always retained. Other nodes are cleared from the app database on the schedule set by the user. (Nodes with PKC keys are always retained for at least 7 days.) This feature only purges nodes from the app that are not stored in the device node database." : {
14341+
1433814342
},
1433914343
"Favorites" : {
1434014344
"localizations" : {
@@ -31617,6 +31621,9 @@
3161731621
}
3161831622
}
3161931623
}
31624+
},
31625+
"Select an emoji" : {
31626+
3162031627
},
3162131628
"Select Channel" : {
3162231629
"localizations" : {
@@ -35547,6 +35554,9 @@
3554735554
}
3554835555
}
3554935556
}
35557+
},
35558+
"Tap to enter emoji" : {
35559+
3555035560
},
3555135561
"Tapback" : {
3555235562
"localizations" : {
@@ -42321,4 +42331,4 @@
4232142331
}
4232242332
},
4232342333
"version" : "1.1"
42324-
}
42334+
}

Meshtastic.xcodeproj/project.pbxproj

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
D93068D52B812B700066FBC8 /* MessageDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D42B812B700066FBC8 /* MessageDestination.swift */; };
116116
D93068D72B8146690066FBC8 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D62B8146690066FBC8 /* MessageText.swift */; };
117117
D93068D92B81509C0066FBC8 /* TapbackResponses.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D82B81509C0066FBC8 /* TapbackResponses.swift */; };
118+
D93068DA2B81509D0066FBC8 /* TapbackInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068D92B81509D0066FBC8 /* TapbackInputView.swift */; };
118119
D93068DB2B81C85E0066FBC8 /* PowerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068DA2B81C85E0066FBC8 /* PowerConfig.swift */; };
119120
D93068DD2B81CA820066FBC8 /* ConfigHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93068DC2B81CA820066FBC8 /* ConfigHeader.swift */; };
120121
D93069082B81DF040066FBC8 /* SaveConfigButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93069072B81DF040066FBC8 /* SaveConfigButton.swift */; };
@@ -201,7 +202,6 @@
201202
DD93800B2BA3F968008BEC06 /* NodeMapContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD93800A2BA3F968008BEC06 /* NodeMapContent.swift */; };
202203
DD93800E2BA74D0C008BEC06 /* ChannelForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD93800D2BA74D0C008BEC06 /* ChannelForm.swift */; };
203204
DD94B7402ACCE3BE00DCD1D1 /* MapSettingsForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD94B73F2ACCE3BE00DCD1D1 /* MapSettingsForm.swift */; };
204-
DD964FBD296E6B01007C176F /* EmojiOnlyTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */; };
205205
DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */; };
206206
DD964FC62975DBFD007C176F /* QueryCoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC52975DBFD007C176F /* QueryCoreData.swift */; };
207207
DD97E96628EFD9820056DDA4 /* MeshtasticLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */; };
@@ -215,6 +215,7 @@
215215
DD9C70112E916EBD00106227 /* UpdateIntervalPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9C70102E916EA200106227 /* UpdateIntervalPicker.swift */; };
216216
DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA0B6B1294CDC55001356EC /* Channels.swift */; };
217217
DDA1C48E28DB49D3009933EC /* ChannelRoles.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */; };
218+
DDA3DFDA2F10B39600D8F103 /* UIKeyboardType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA3DFD92F10B39600D8F103 /* UIKeyboardType.swift */; };
218219
DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */; };
219220
DDA9515A2BC6624100CEA535 /* TelemetryWeather.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA951592BC6624100CEA535 /* TelemetryWeather.swift */; };
220221
DDA9515C2BC6631200CEA535 /* TelemetryEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */; };
@@ -427,6 +428,7 @@
427428
D93068D42B812B700066FBC8 /* MessageDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageDestination.swift; sourceTree = "<group>"; };
428429
D93068D62B8146690066FBC8 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = "<group>"; };
429430
D93068D82B81509C0066FBC8 /* TapbackResponses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TapbackResponses.swift; sourceTree = "<group>"; };
431+
D93068D92B81509D0066FBC8 /* TapbackInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TapbackInputView.swift; sourceTree = "<group>"; };
430432
D93068DA2B81C85E0066FBC8 /* PowerConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerConfig.swift; sourceTree = "<group>"; };
431433
D93068DC2B81CA820066FBC8 /* ConfigHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigHeader.swift; sourceTree = "<group>"; };
432434
D93069062B81D8900066FBC8 /* MeshtasticDataModelV 27.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 27.xcdatamodel"; sourceTree = "<group>"; };
@@ -545,7 +547,6 @@
545547
DD93800A2BA3F968008BEC06 /* NodeMapContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMapContent.swift; sourceTree = "<group>"; };
546548
DD93800D2BA74D0C008BEC06 /* ChannelForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelForm.swift; sourceTree = "<group>"; };
547549
DD94B73F2ACCE3BE00DCD1D1 /* MapSettingsForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSettingsForm.swift; sourceTree = "<group>"; };
548-
DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiOnlyTextField.swift; sourceTree = "<group>"; };
549550
DD964FC029724F6D007C176F /* MeshtasticDataModelV6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV6.xcdatamodel; sourceTree = "<group>"; };
550551
DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointEntityExtension.swift; sourceTree = "<group>"; };
551552
DD964FC52975DBFD007C176F /* QueryCoreData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryCoreData.swift; sourceTree = "<group>"; };
@@ -563,6 +564,7 @@
563564
DDA0B6B1294CDC55001356EC /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = "<group>"; };
564565
DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelRoles.swift; sourceTree = "<group>"; };
565566
DDA28B1B2D32C89200EF726F /* MeshtasticDataModelV 48.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 48.xcdatamodel"; sourceTree = "<group>"; };
567+
DDA3DFD92F10B39600D8F103 /* UIKeyboardType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKeyboardType.swift; sourceTree = "<group>"; };
566568
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshPackets.swift; sourceTree = "<group>"; };
567569
DDA951592BC6624100CEA535 /* TelemetryWeather.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelemetryWeather.swift; sourceTree = "<group>"; };
568570
DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryEnums.swift; sourceTree = "<group>"; };
@@ -1250,6 +1252,7 @@
12501252
D93068D62B8146690066FBC8 /* MessageText.swift */,
12511253
D93068D22B8129510066FBC8 /* MessageContextMenuItems.swift */,
12521254
D93068D82B81509C0066FBC8 /* TapbackResponses.swift */,
1255+
D93068D92B81509D0066FBC8 /* TapbackInputView.swift */,
12531256
);
12541257
path = Messages;
12551258
sourceTree = "<group>";
@@ -1291,7 +1294,6 @@
12911294
DD1BEF492E0292220090CE24 /* KeychainHelper.swift */,
12921295
DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */,
12931296
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */,
1294-
DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */,
12951297
DD3619142B1EF9F900C41C8C /* LocationsHandler.swift */,
12961298
6D825E612C34786C008DBEE4 /* CommonRegex.swift */,
12971299
3D3417B32E2730EC006A988B /* GeoJSONOverlayManager.swift */,
@@ -1371,6 +1373,7 @@
13711373
DDDB444729F8A9C900EE2349 /* String.swift */,
13721374
DD77093E2AA1B146007A8BF0 /* UIColor.swift */,
13731375
DDDB444F29F8AC9C00EE2349 /* UIImage.swift */,
1376+
DDA3DFD92F10B39600D8F103 /* UIKeyboardType.swift */,
13741377
DDDB443F29F79AB000EE2349 /* UserDefaults.swift */,
13751378
DDB75A0E2A05920E006ED576 /* FileManager.swift */,
13761379
DDB75A102A059258006ED576 /* Url.swift */,
@@ -1668,7 +1671,6 @@
16681671
DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */,
16691672
D9C9839D2B79CFD700BDBE6A /* TextMessageSize.swift in Sources */,
16701673
DDC94FCE29CF55310082EA6E /* RtttlConfig.swift in Sources */,
1671-
DD964FBD296E6B01007C176F /* EmojiOnlyTextField.swift in Sources */,
16721674
DD1BEF4E2E03916A0090CE24 /* ChannelsHelp.swift in Sources */,
16731675
DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */,
16741676
BCD93CBA2D9E11A2006C9214 /* DisconnectNodeIntent.swift in Sources */,
@@ -1801,6 +1803,7 @@
18011803
DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */,
18021804
DDCE4E2C2869F92900BE9F8F /* UserConfig.swift in Sources */,
18031805
BCB613852C68703800485544 /* NodePositionIntent.swift in Sources */,
1806+
DDA3DFDA2F10B39600D8F103 /* UIKeyboardType.swift in Sources */,
18041807
DDB75A212A12B954006ED576 /* LoRaSignalStrength.swift in Sources */,
18051808
DD6193752862F6E600E59241 /* ExternalNotificationConfig.swift in Sources */,
18061809
DD268D8E2BCC90E2008073AE /* RouteEnums.swift in Sources */,
@@ -1809,6 +1812,7 @@
18091812
DD4975A52B147BA90026544E /* AmbientLightingConfig.swift in Sources */,
18101813
3D3417D22E2DC260006A988B /* MapDataManager.swift in Sources */,
18111814
D93068D92B81509C0066FBC8 /* TapbackResponses.swift in Sources */,
1815+
D93068DA2B81509D0066FBC8 /* TapbackInputView.swift in Sources */,
18121816
DDA9F5E82E77FAC100E70DEB /* AnimatedNodePin.swift in Sources */,
18131817
DDF82CBD2D5BC69200DC25EC /* NavigateToButton.swift in Sources */,
18141818
8D3F8A3F2D44BB02009EAAA4 /* PowerMetrics.swift in Sources */,
@@ -2102,7 +2106,7 @@
21022106
"@executable_path/Frameworks",
21032107
);
21042108
MACOSX_DEPLOYMENT_TARGET = 14.6;
2105-
MARKETING_VERSION = 2.7.6;
2109+
MARKETING_VERSION = 2.7.7;
21062110
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
21072111
PRODUCT_NAME = "$(TARGET_NAME)";
21082112
SUPPORTS_MACCATALYST = YES;
@@ -2137,7 +2141,7 @@
21372141
"@executable_path/Frameworks",
21382142
);
21392143
MACOSX_DEPLOYMENT_TARGET = 14.6;
2140-
MARKETING_VERSION = 2.7.6;
2144+
MARKETING_VERSION = 2.7.7;
21412145
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
21422146
PRODUCT_NAME = "$(TARGET_NAME)";
21432147
SUPPORTS_MACCATALYST = YES;
@@ -2169,7 +2173,7 @@
21692173
"@executable_path/../../Frameworks",
21702174
);
21712175
MACOSX_DEPLOYMENT_TARGET = 14.6;
2172-
MARKETING_VERSION = 2.7.6;
2176+
MARKETING_VERSION = 2.7.7;
21732177
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
21742178
PRODUCT_NAME = "$(TARGET_NAME)";
21752179
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2202,7 +2206,7 @@
22022206
"@executable_path/../../Frameworks",
22032207
);
22042208
MACOSX_DEPLOYMENT_TARGET = 14.6;
2205-
MARKETING_VERSION = 2.7.6;
2209+
MARKETING_VERSION = 2.7.7;
22062210
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
22072211
PRODUCT_NAME = "$(TARGET_NAME)";
22082212
PROVISIONING_PROFILE_SPECIFIER = "";

Meshtastic/Accessory/Accessory Manager/AccessoryManager+Connect.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ actor SequentialSteps {
352352
return
353353
}
354354
isRunning = false
355-
return
356355
throw AccessoryError.tooManyRetries
357356
}
358357

Meshtastic/Accessory/Accessory Manager/AccessoryManager+Discovery.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extension AccessoryManager {
1515
let tasks = transports.map { transport in
1616
Task {
1717
Logger.transport.info("🔎 [Discovery] Discovery stream started for transport \(String(describing: transport.type), privacy: .public)")
18-
for await event in transport.discoverDevices() {
18+
for await event in await transport.discoverDevices() {
1919
continuation.yield(event)
2020
}
2121
Logger.transport.info("🔎 [Discovery] Discovery stream closed for transport \(String(describing: transport.type), privacy: .public)")

Meshtastic/Accessory/Accessory Manager/AccessoryManager+ToRadio.swift

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,6 @@ extension AccessoryManager {
441441
Logger.services.error("Error while sending saveChannelSet request. No active device.")
442442
throw AccessoryError.ioFailed("No active device")
443443
}
444-
var i: Int32 = 0
445-
var myInfo: MyInfoEntity
446444
// Before we get started delete the existing channels from the myNodeInfo
447445
if !addChannels {
448446
tryClearExistingChannels()
@@ -451,64 +449,74 @@ extension AccessoryManager {
451449
let decodedString = base64UrlString.base64urlToBase64()
452450
if let decodedData = Data(base64Encoded: decodedString) {
453451
let channelSet: ChannelSet = try ChannelSet(serializedBytes: decodedData)
452+
453+
var myInfo: MyInfoEntity!
454+
var i: Int32 = 0
455+
456+
if addChannels {
457+
let fetchMyInfoRequest = MyInfoEntity.fetchRequest()
458+
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(deviceNum))
459+
460+
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest)
461+
if fetchedMyInfo.count != 1 {
462+
throw AccessoryError.appError("MyInfo not found")
463+
}
464+
465+
// We are trying to add a channel so lets get the last index
466+
myInfo = fetchedMyInfo[0]
467+
i = Int32(myInfo.channels?.count ?? -1)
468+
469+
// Bail out if the index is negative or bigger than our max of 8
470+
if i < 0 || i > 8 {
471+
throw AccessoryError.appError("Index out of range \(i)")
472+
}
473+
}
474+
454475
for cs in channelSet.settings {
476+
455477
if addChannels {
456-
// We are trying to add a channel so lets get the last index
457-
let fetchMyInfoRequest = MyInfoEntity.fetchRequest()
458-
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(deviceNum))
459-
do {
460-
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest)
461-
if fetchedMyInfo.count == 1 {
462-
i = Int32(fetchedMyInfo[0].channels?.count ?? -1)
463-
myInfo = fetchedMyInfo[0]
464-
// Bail out if the index is negative or bigger than our max of 8
465-
if i < 0 || i > 8 {
466-
throw AccessoryError.appError("Index out of range \(i)")
467-
}
468-
// Bail out if there are no channels or if the same channel name already exists
469-
guard let mutableChannels = myInfo.channels!.mutableCopy() as? NSMutableOrderedSet else {
470-
throw AccessoryError.appError("No channels or channel")
471-
}
472-
if mutableChannels.first(where: {($0 as AnyObject).name == cs.name }) is ChannelEntity {
473-
throw AccessoryError.appError("Channel already exists")
474-
}
475-
}
476-
} catch {
477-
Logger.data.error("Failed to find a node MyInfo to save these channels to: \(error.localizedDescription, privacy: .public)")
478+
guard let mutableChannels = myInfo.channels?.mutableCopy() as? NSMutableOrderedSet else {
479+
throw AccessoryError.appError("No channels or channel")
480+
}
481+
482+
// Bail out if there are no channels or if the same channel name already exists
483+
if mutableChannels.first(where: { ($0 as AnyObject).name == cs.name }) is ChannelEntity {
484+
throw AccessoryError.appError("Channel already exists")
478485
}
479486
}
480487

481488
var chan = Channel()
482-
if i == 0 {
483-
chan.role = Channel.Role.primary
484-
} else {
485-
chan.role = Channel.Role.secondary
486-
}
489+
chan.role = (i == 0) ? .primary : .secondary
487490
chan.settings = cs
488491
chan.index = i
489492
i += 1
490493

491494
var adminPacket = AdminMessage()
492495
adminPacket.setChannel = chan
493-
var meshPacket: MeshPacket = MeshPacket()
496+
497+
var meshPacket = MeshPacket()
494498
meshPacket.to = UInt32(deviceNum)
495-
meshPacket.from = UInt32(deviceNum)
499+
meshPacket.from = UInt32(deviceNum)
496500
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
497-
meshPacket.priority = MeshPacket.Priority.reliable
501+
meshPacket.priority = MeshPacket.Priority.reliable
498502
meshPacket.wantAck = true
499503
meshPacket.channel = 0
500-
guard let adminData: Data = try? adminPacket.serializedData() else {
504+
505+
guard let adminData = try? adminPacket.serializedData() else {
501506
throw AccessoryError.ioFailed("saveChannelSet: Unable to serialize Admin packet")
502507
}
508+
503509
var dataMessage = DataMessage()
504510
dataMessage.payload = adminData
505511
dataMessage.portnum = PortNum.adminApp
506512
meshPacket.decoded = dataMessage
507-
var toRadio: ToRadio!
508-
toRadio = ToRadio()
513+
514+
var toRadio = ToRadio()
509515
toRadio.packet = meshPacket
516+
510517
let logString = String.localizedStringWithFormat("Sent a Channel for: %@ Channel Index %d".localized, String(deviceNum), chan.index)
511518
try await send(toRadio, debugDescription: logString)
519+
channelPacket(channel: chan, fromNum: self.activeDeviceNum ?? 0, context: context)
512520
}
513521
if !addChannels {
514522
// Save the LoRa Config and the device will reboot

Meshtastic/Accessory/Accessory Manager/AccessoryManager.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ class AccessoryManager: ObservableObject, MqttClientProxyManagerDelegate {
196196
Logger.transport.error("Unable to send wantConfig (config): No device connected")
197197
return
198198
}
199+
200+
_ = clearStaleNodes(nodeExpireDays: Int(UserDefaults.purgeStaleNodeDays), context: self.context)
199201

200202
try await withTaskCancellationHandler {
201203
var toRadio: ToRadio = ToRadio()

Meshtastic/Accessory/Protocols/Connection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protocol Connection: Actor {
1414
var isConnected: Bool { get }
1515
func send(_ data: ToRadio) async throws
1616
func connect() async throws -> AsyncStream<ConnectionEvent>
17-
func disconnect(withError: Error?, shouldReconnect: Bool) throws
17+
func disconnect(withError: Error?, shouldReconnect: Bool) async throws
1818
func drainPendingPackets() async throws
1919
func startDrainPendingPackets() throws
2020

Meshtastic/Accessory/Protocols/Transport.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ enum DiscoveryEvent {
4242

4343
protocol Transport {
4444
var type: TransportType { get }
45-
var status: TransportStatus { get }
45+
var status: TransportStatus { get async }
4646

4747
// Discovers devices asynchronously. For ongoing scans (e.g., BLE), this can yield via AsyncStream.
48-
func discoverDevices() -> AsyncStream<DiscoveryEvent>
48+
func discoverDevices() async -> AsyncStream<DiscoveryEvent>
4949

5050
// Connects to a device and returns a Connection.
5151
func connect(to device: Device) async throws -> any Connection

0 commit comments

Comments
 (0)