2021-09-10 07:41:26 -07:00
import Foundation
2021-09-12 17:51:10 -07:00
import CoreData
2021-09-10 07:41:26 -07:00
import CoreBluetooth
2021-09-14 21:38:12 -07:00
import SwiftUI
2022-01-04 22:57:33 -08:00
import MapKit
2024-06-07 22:09:20 -05:00
import MeshtasticProtobufs
2023-08-01 22:28:02 -07:00
import CocoaMQTT
2024-06-03 02:17:55 -07:00
import OSLog
2021-09-10 07:41:26 -07:00
2021-11-29 15:59:06 -08:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2021-09-10 21:50:54 -07:00
// M e s h t a s t i c B L E D e v i c e M a n a g e r
2021-11-29 15:59:06 -08:00
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2023-08-08 18:10:50 -07:00
class BLEManager : NSObject , CBPeripheralDelegate , MqttClientProxyManagerDelegate , ObservableObject {
2024-07-10 16:03:38 -05:00
private let context : NSManagedObjectContext
private let updateCoreDataController : UpdateCoreDataController
private let queryCoreDataController : QueryCoreDataController
2021-12-12 17:17:46 -08:00
private var centralManager : CBCentralManager !
2022-12-04 00:28:26 -08:00
@ Published var peripherals : [ Peripheral ] = [ ]
2022-09-28 15:50:35 -07:00
@ Published var connectedPeripheral : Peripheral !
2022-12-07 16:50:24 -08:00
@ Published var lastConnectionError : String
2022-12-04 06:56:55 -08:00
@ Published var invalidVersion = false
2022-12-05 19:59:07 -08:00
@ Published var isSwitchedOn : Bool = false
2023-01-03 21:45:10 -08:00
@ Published var automaticallyReconnect : Bool = true
2023-08-15 18:45:47 -07:00
@ Published var mqttProxyConnected : Bool = false
2024-04-05 17:14:04 -07:00
@ Published var mqttError : String = " "
2023-09-04 20:17:09 -07:00
@ StateObject var appState = AppState . shared
2023-02-27 16:10:00 -08:00
public var minimumVersion = " 2.0.0 "
2022-12-04 00:28:26 -08:00
public var connectedVersion : String
public var isConnecting : Bool = false
public var isConnected : Bool = false
public var isSubscribed : Bool = false
2022-06-11 09:50:25 -07:00
private var configNonce : UInt32 = 1
2021-10-22 10:03:50 -07:00
var timeoutTimer : Timer ?
2021-10-27 20:31:20 -07:00
var timeoutTimerCount = 0
2022-02-22 09:08:06 -10:00
var positionTimer : Timer ?
2024-02-05 23:31:54 -07:00
static let emptyNodeNum : UInt32 = 4294967295
2023-08-01 22:28:02 -07:00
let mqttManager = MqttClientProxyManager . shared
2023-08-19 19:38:01 -05:00
var wantRangeTestPackets = false
2023-12-10 12:38:01 -08:00
var wantStoreAndForwardPackets = false
2022-09-28 15:50:35 -07:00
/* M e s h t a s t i c S e r v i c e D e t a i l s */
var TORADIO_characteristic : CBCharacteristic !
var FROMRADIO_characteristic : CBCharacteristic !
var FROMNUM_characteristic : CBCharacteristic !
2024-07-02 08:04:09 -05:00
var LEGACY_LOGRADIO_characteristic : CBCharacteristic !
2024-06-23 07:09:14 -07:00
var LOGRADIO_characteristic : CBCharacteristic !
2022-09-28 15:50:35 -07:00
let meshtasticServiceCBUUID = CBUUID ( string : " 0x6BA1B218-15A8-461F-9FA8-5DCAE273EAFD " )
let TORADIO_UUID = CBUUID ( string : " 0xF75C76D2-129E-4DAD-A1DD-7866124401E7 " )
2022-10-13 14:08:36 -07:00
let FROMRADIO_UUID = CBUUID ( string : " 0x2C55E69E-4993-11ED-B878-0242AC120002 " )
2022-10-11 14:25:59 -07:00
let EOL_FROMRADIO_UUID = CBUUID ( string : " 0x8BA2BCC2-EE02-4A55-A531-C525C5E454D5 " )
2022-09-28 15:50:35 -07:00
let FROMNUM_UUID = CBUUID ( string : " 0xED9DA18C-A800-4F66-A670-AA7547E34453 " )
2024-07-02 08:04:09 -05:00
let LEGACY_LOGRADIO_UUID = CBUUID ( string : " 0x6C6FD238-78FA-436B-AACF-15C5BE1EF2E2 " )
let LOGRADIO_UUID = CBUUID ( string : " 0x5a3d6e49-06e6-4423-9944-e9de8cdf9547 " )
2024-07-10 16:03:38 -05:00
// MARK: i n i t
init (
context : NSManagedObjectContext ,
updateCoreDataController : UpdateCoreDataController ,
queryCoreDataController : QueryCoreDataController
) {
2022-09-28 15:50:35 -07:00
self . lastConnectionError = " "
2022-08-06 08:07:16 -07:00
self . connectedVersion = " 0.0.0 "
2024-07-10 16:03:38 -05:00
self . context = context
self . updateCoreDataController = updateCoreDataController
self . queryCoreDataController = queryCoreDataController
2022-09-28 15:50:35 -07:00
super . init ( )
2023-02-27 16:10:00 -08:00
centralManager = CBCentralManager ( delegate : self , queue : nil )
2023-08-08 18:10:50 -07:00
mqttManager . delegate = self
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2021-12-12 17:17:46 -08:00
// MARK: S c a n n i n g f o r B L E D e v i c e s
2022-09-28 15:50:35 -07:00
// S c a n f o r n e a r b y B L E d e v i c e s u s i n g t h e M e s h t a s t i c B L E s e r v i c e I D
func startScanning ( ) {
if isSwitchedOn {
2023-09-17 19:42:03 -07:00
centralManager . scanForPeripherals ( withServices : [ meshtasticServiceCBUUID ] , options : [ CBCentralManagerScanOptionAllowDuplicatesKey : false ] )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ✅ [BLE] Scanning Started " )
2022-09-28 15:50:35 -07:00
}
}
2024-07-10 16:03:38 -05:00
2021-12-12 17:17:46 -08:00
// S t o p S c a n n i n g F o r B L E D e v i c e s
2022-09-28 15:50:35 -07:00
func stopScanning ( ) {
if centralManager . isScanning {
centralManager . stopScan ( )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " 🛑 [BLE] Stopped Scanning " )
2022-09-28 15:50:35 -07:00
}
}
2024-07-10 16:03:38 -05:00
2021-12-12 17:17:46 -08:00
// MARK: B L E C o n n e c t f u n c t i o n s
2021-10-22 10:03:50 -07:00
// / T h e a c t i o n a f t e r t h e t i m e o u t - t i m e r h a s f i r e d
// /
// / - P a r a m e t e r s :
// / - t i m e r : T h e t i m e t h a t f i r e d t h e e v e n t
// /
2021-11-29 15:59:06 -08:00
@objc func timeoutTimerFired ( timer : Timer ) {
2021-12-15 23:53:45 -08:00
guard let timerContext = timer . userInfo as ? [ String : String ] else { return }
let name : String = timerContext [ " name " , default : " Unknown " ]
2024-07-10 16:03:38 -05:00
2021-10-28 00:15:47 -07:00
self . timeoutTimerCount += 1
2022-10-12 15:26:25 -07:00
self . lastConnectionError = " "
2024-07-10 16:03:38 -05:00
2023-01-02 01:27:57 -08:00
if timeoutTimerCount = = 10 {
2021-11-04 08:36:55 -07:00
if connectedPeripheral != nil {
2021-10-22 20:58:20 -07:00
self . centralManager ? . cancelPeripheralConnection ( connectedPeripheral . peripheral )
}
2021-11-04 08:36:55 -07:00
connectedPeripheral = nil
2022-08-11 23:34:09 -07:00
if self . timeoutTimer != nil {
2024-07-10 16:03:38 -05:00
2022-08-11 23:34:09 -07:00
self . timeoutTimer ! . invalidate ( )
}
2022-10-12 15:26:25 -07:00
self . isConnected = false
self . isConnecting = false
2023-05-05 09:27:24 -07:00
self . lastConnectionError = " 🚨 " + String . localizedStringWithFormat ( " ble.connection.timeout %d %@ " . localized , timeoutTimerCount , name )
2022-10-15 10:14:08 -07:00
MeshLogger . log ( lastConnectionError )
2022-10-12 15:26:25 -07:00
self . timeoutTimerCount = 0
self . startScanning ( )
2021-11-29 15:59:06 -08:00
} else {
2024-06-23 16:11:02 -07:00
Logger . services . info ( " 🚨 [BLE] Connecting 2 Second Timeout Timer Fired \( self . timeoutTimerCount , privacy : . public ) Time(s): \( name , privacy : . public ) " )
2021-10-22 10:03:50 -07:00
}
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
// C o n n e c t t o a s p e c i f i c p e r i p h e r a l
func connectTo ( peripheral : CBPeripheral ) {
stopScanning ( )
2022-10-22 07:35:55 -07:00
DispatchQueue . main . async {
self . isConnecting = true
self . lastConnectionError = " "
2023-01-03 21:45:10 -08:00
self . automaticallyReconnect = true
2022-10-22 07:35:55 -07:00
}
2022-10-12 16:09:55 -07:00
if connectedPeripheral != nil {
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ℹ ️ [BLE] Disconnecting from: \( self . connectedPeripheral . name , privacy : . public ) to connect to \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2022-10-12 16:09:55 -07:00
disconnectPeripheral ( )
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2022-10-12 16:09:55 -07:00
centralManager ? . connect ( peripheral )
2022-08-04 23:03:46 -06:00
// I n v a l i d a t e a n y e x i s t i n g t i m e r
2022-10-12 16:09:55 -07:00
if timeoutTimer != nil {
timeoutTimer ! . invalidate ( )
2022-08-11 23:34:09 -07:00
}
2021-10-23 10:27:10 -07:00
// U s e a t i m e r t o k e e p t r a c k o f c o n n e c t i n g p e r i p h e r a l s , c o n t e x t t o p a s s t h e r a d i o n a m e w i t h t h e t i m e r a n d t h e R u n L o o p t o p r e v e n t
// t h e t i m e r f r o m r u n n i n g o n t h e m a i n U I t h r e a d
2022-10-12 15:46:53 -07:00
let context = [ " name " : " \( peripheral . name ? ? " Unknown " ) " ]
2022-10-12 16:09:55 -07:00
timeoutTimer = Timer . scheduledTimer ( timeInterval : 1.5 , target : self , selector : #selector ( timeoutTimerFired ) , userInfo : context , repeats : true )
RunLoop . current . add ( timeoutTimer ! , forMode : . common )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ℹ ️ BLE Connecting: \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2024-04-13 09:46:13 -07:00
// D i s c o n n e c t C o n n e c t e d P e r i p h e r a l
func cancelPeripheralConnection ( ) {
2024-07-10 16:03:38 -05:00
2024-04-13 09:46:13 -07:00
if mqttProxyConnected {
mqttManager . mqttClientProxy ? . disconnect ( )
}
FROMRADIO_characteristic = nil
isConnecting = false
isConnected = false
isSubscribed = false
2024-04-30 12:26:57 -07:00
self . connectedPeripheral = nil
2024-04-13 09:46:13 -07:00
invalidVersion = false
connectedVersion = " 0.0.0 "
connectedPeripheral = nil
if timeoutTimer != nil {
timeoutTimer ! . invalidate ( )
}
2024-04-30 12:26:57 -07:00
automaticallyReconnect = false
stopScanning ( )
2024-04-13 09:46:13 -07:00
startScanning ( )
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
// D i s c o n n e c t C o n n e c t e d P e r i p h e r a l
2023-01-03 21:45:10 -08:00
func disconnectPeripheral ( reconnect : Bool = true ) {
2024-07-10 16:03:38 -05:00
2021-11-21 13:48:28 -08:00
guard let connectedPeripheral = connectedPeripheral else { return }
2023-10-20 16:14:29 -07:00
if mqttProxyConnected {
mqttManager . mqttClientProxy ? . disconnect ( )
}
2023-01-03 21:45:10 -08:00
automaticallyReconnect = reconnect
2022-09-28 15:50:35 -07:00
centralManager ? . cancelPeripheralConnection ( connectedPeripheral . peripheral )
2022-10-11 14:25:59 -07:00
FROMRADIO_characteristic = nil
2022-09-28 15:50:35 -07:00
isConnected = false
2022-10-18 13:53:50 -07:00
isSubscribed = false
2022-09-28 15:50:35 -07:00
invalidVersion = false
connectedVersion = " 0.0.0 "
2024-04-13 09:46:13 -07:00
stopScanning ( )
2022-10-12 16:09:55 -07:00
startScanning ( )
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2024-04-13 09:46:13 -07:00
// C a l l e d e a c h t i m e a p e r i p h e r a l i s c o n n e c t e d
2022-09-28 15:50:35 -07:00
func centralManager ( _ central : CBCentralManager , didConnect peripheral : CBPeripheral ) {
2022-10-22 07:41:40 -07:00
isConnecting = false
isConnected = true
2023-04-26 09:19:45 -07:00
if UserDefaults . preferredPeripheralId . count < 1 {
UserDefaults . preferredPeripheralId = peripheral . identifier . uuidString
2022-10-01 09:37:10 -07:00
}
2022-10-22 07:35:55 -07:00
// I n v a l i d a t e a n d r e s e t c o n n e c t i o n t i m e r c o u n t
2022-10-22 07:49:39 -07:00
timeoutTimerCount = 0
if timeoutTimer != nil {
timeoutTimer ! . invalidate ( )
2022-08-11 23:34:09 -07:00
}
2024-07-10 16:03:38 -05:00
2022-10-22 07:35:55 -07:00
// r e m o v e a n y c o n n e c t i o n e r r o r s
self . lastConnectionError = " "
2022-09-09 08:25:52 -07:00
// M a p t h e p e r i p h e r a l t o t h e c o n n e c t e d P e r i p h e r a l O b s e r v e d O b j e c t s
2022-09-28 15:50:35 -07:00
connectedPeripheral = peripherals . filter ( { $0 . peripheral . identifier = = peripheral . identifier } ) . first
2022-09-09 08:25:52 -07:00
if connectedPeripheral != nil {
connectedPeripheral . peripheral . delegate = self
2023-03-06 10:33:18 -08:00
} else {
2022-09-09 08:25:52 -07:00
// w e a r e n u l l j u s t d i s c o n n e c t a n d s t a r t o v e r
2024-06-25 08:29:26 -07:00
lastConnectionError = " 🚫 [BLE] Bluetooth connection error, please try again. "
2022-10-22 07:41:40 -07:00
disconnectPeripheral ( )
2022-09-09 08:25:52 -07:00
return
}
2021-10-23 10:27:10 -07:00
// D i s c o v e r S e r v i c e s
2022-12-05 19:32:58 -08:00
peripheral . discoverServices ( [ meshtasticServiceCBUUID ] )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ✅ [BLE] Connected: \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2021-12-12 17:17:46 -08:00
// C a l l e d w h e n a P e r i p h e r a l f a i l s t o c o n n e c t
2021-11-21 13:48:28 -08:00
func centralManager ( _ central : CBCentralManager , didFailToConnect peripheral : CBPeripheral , error : Error ? ) {
2024-04-13 09:46:13 -07:00
cancelPeripheralConnection ( )
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚫 [BLE] Failed to Connect: \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2021-11-21 13:48:28 -08:00
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
// D i s c o n n e c t P e r i p h e r a l E v e n t
func centralManager ( _ central : CBCentralManager , didDisconnectPeripheral peripheral : CBPeripheral , error : Error ? ) {
2021-10-23 00:19:23 -07:00
self . connectedPeripheral = nil
2022-10-12 15:26:25 -07:00
self . isConnecting = false
2022-12-09 18:19:00 -08:00
self . isConnected = false
2022-10-18 13:53:50 -07:00
self . isSubscribed = false
2023-11-01 15:59:22 -07:00
let manager = LocalNotificationManager ( )
2022-09-28 15:50:35 -07:00
if let e = error {
2021-10-23 10:27:10 -07:00
// h t t p s : / / d e v e l o p e r . a p p l e . c o m / d o c u m e n t a t i o n / c o r e b l u e t o o t h / c b e r r o r / c o d e
2022-09-28 15:50:35 -07:00
let errorCode = ( e as NSError ) . code
if errorCode = = 6 { // C B E r r o r . C o d e . c o n n e c t i o n T i m e o u t T h e c o n n e c t i o n h a s t i m e d o u t u n e x p e c t e d l y .
2021-10-22 10:03:50 -07:00
// H a p p e n s w h e n d e v i c e i s m a n u a l l y r e s e t / p o w e r e d o f f
2023-05-05 09:27:24 -07:00
lastConnectionError = " 🚨 " + String . localizedStringWithFormat ( " ble.errorcode.6 %@ " . localized , e . localizedDescription )
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚨 [BLE] Disconnected: \( peripheral . name ? ? " Unknown " , privacy : . public ) Error Code: \( errorCode , privacy : . public ) Error: \( e . localizedDescription , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
} else if errorCode = = 7 { // C B E r r o r . C o d e . p e r i p h e r a l D i s c o n n e c t e d T h e s p e c i f i e d d e v i c e h a s d i s c o n n e c t e d f r o m u s .
// S e e m s t o b e w h a t i s r e c e i v e d w h e n a t b e a m s l e e p s , i m m e d i a t e l y r e c c o n n e c t i n g d o e s n o t w o r k .
2023-11-07 15:25:20 -08:00
if UserDefaults . preferredPeripheralId = = peripheral . identifier . uuidString {
2023-11-01 15:59:22 -07:00
manager . notifications = [
Notification (
id : ( peripheral . identifier . uuidString ) ,
2023-11-07 15:25:20 -08:00
title : " Radio Disconnected " ,
subtitle : " \( peripheral . name ? ? " unknown " . localized ) " ,
2024-01-20 14:05:29 -08:00
content : e . localizedDescription ,
target : " bluetooth " ,
path : " meshtastic://bluetooth "
2023-11-01 15:59:22 -07:00
)
]
manager . schedule ( )
}
2022-12-30 01:36:06 -08:00
lastConnectionError = " 🚨 \( e . localizedDescription ) "
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚨 [BLE] Disconnected: \( peripheral . name ? ? " Unknown " , privacy : . public ) Error Code: \( errorCode , privacy : . public ) Error: \( e . localizedDescription , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
} else if errorCode = = 14 { // P e e r r e m o v e d p a i r i n g i n f o r m a t i o n
// F o r g e t t i n g a n d r e c o n n e c t i n g s e e m s t o b e n e c e s s a r y s o w e n e e d t o s h o w t h e u s e r a n e r r o r t e l l i n g t h e m t o d o t h a t
2023-05-05 09:27:24 -07:00
lastConnectionError = " 🚨 " + String . localizedStringWithFormat ( " ble.errorcode.14 %@ " . localized , e . localizedDescription )
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚨 [BLE] Disconnected: \( peripheral . name ? ? " Unknown " ) Error Code: \( errorCode , privacy : . public ) Error: \( self . lastConnectionError , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
} else {
2023-11-07 15:25:20 -08:00
if UserDefaults . preferredPeripheralId = = peripheral . identifier . uuidString {
2023-11-01 15:59:22 -07:00
manager . notifications = [
Notification (
id : ( peripheral . identifier . uuidString ) ,
2023-11-07 15:25:20 -08:00
title : " Radio Disconnected " ,
subtitle : " \( peripheral . name ? ? " unknown " . localized ) " ,
2024-01-20 14:05:29 -08:00
content : e . localizedDescription ,
target : " bluetooth " ,
path : " meshtastic://bluetooth "
2023-11-01 15:59:22 -07:00
)
]
manager . schedule ( )
}
2023-01-01 14:48:50 -08:00
lastConnectionError = " 🚨 \( e . localizedDescription ) "
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚨 [BLE] Disconnected: \( peripheral . name ? ? " Unknown " , privacy : . public ) Error Code: \( errorCode , privacy : . public ) Error: \( e . localizedDescription , privacy : . public ) " )
2021-10-23 00:19:23 -07:00
}
2022-09-28 15:50:35 -07:00
} else {
// D i s c o n n e c t e d w i t h o u t e r r o r w h i c h i n d i c a t e s u s e r i n t e n t t o d i s c o n n e c t
2021-10-23 00:19:23 -07:00
// H a p p e n s w h e n s w i p i n g t o d i s c o n n e c t
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ℹ ️ [BLE] Disconnected: \( peripheral . name ? ? " Unknown " , privacy : . public ) : User Initiated Disconnect " )
2022-09-28 15:50:35 -07:00
}
2022-12-07 16:50:24 -08:00
// S t a r t a s c a n s o t h e d i s c o n n e c t e d p e r i p h e r a l i s m o v e d t o t h e p e r i p h e r a l s [ ] i f i t i s a w a k e
self . startScanning ( )
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
// MARK: P e r i p h e r a l S e r v i c e s f u n c t i o n s
func peripheral ( _ peripheral : CBPeripheral , didDiscoverServices error : Error ? ) {
2024-05-31 16:42:34 -05:00
if let error {
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚫 [BLE] Discover Services error \( error . localizedDescription , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
}
guard let services = peripheral . services else { return }
2024-06-02 18:32:14 -07:00
for service in services where service . uuid = = meshtasticServiceCBUUID {
2024-07-02 08:04:09 -05:00
peripheral . discoverCharacteristics ( [ TORADIO_UUID , FROMRADIO_UUID , FROMNUM_UUID , LEGACY_LOGRADIO_UUID , LOGRADIO_UUID ] , for : service )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ✅ [BLE] Service for Meshtastic discovered by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
}
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
// MARK: D i s c o v e r C h a r a c t e r i s t i c s E v e n t
func peripheral ( _ peripheral : CBPeripheral , didDiscoverCharacteristicsFor service : CBService , error : Error ? ) {
2024-07-10 16:03:38 -05:00
2024-05-31 16:42:34 -05:00
if let error {
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚫 [BLE] Discover Characteristics error for \( peripheral . name ? ? " Unknown " , privacy : . public ) \( error . localizedDescription , privacy : . public ) disconnecting device " )
2022-11-02 06:02:58 -07:00
// T r y a n d s t o p c r a s h e s w h e n t h i s e r r o r o c c u r s
disconnectPeripheral ( )
return
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
guard let characteristics = service . characteristics else { return }
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
for characteristic in characteristics {
2021-11-29 16:51:59 -08:00
switch characteristic . uuid {
2024-07-10 16:03:38 -05:00
2021-11-29 16:51:59 -08:00
case TORADIO_UUID :
2024-06-23 13:08:15 -07:00
Logger . services . info ( " ✅ [BLE] did discover TORADIO characteristic for Meshtastic by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2021-11-29 16:51:59 -08:00
TORADIO_characteristic = characteristic
2024-07-10 16:03:38 -05:00
2021-11-29 16:51:59 -08:00
case FROMRADIO_UUID :
2024-06-23 13:08:15 -07:00
Logger . services . info ( " ✅ [BLE] did discover FROMRADIO characteristic for Meshtastic by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2021-11-29 16:51:59 -08:00
FROMRADIO_characteristic = characteristic
peripheral . readValue ( for : FROMRADIO_characteristic )
2024-07-10 16:03:38 -05:00
2021-11-29 16:51:59 -08:00
case FROMNUM_UUID :
2024-06-23 13:08:15 -07:00
Logger . services . info ( " ✅ [BLE] did discover FROMNUM (Notify) characteristic for Meshtastic by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2021-11-29 16:51:59 -08:00
FROMNUM_characteristic = characteristic
peripheral . setNotifyValue ( true , for : characteristic )
2024-07-10 16:03:38 -05:00
2024-07-02 13:13:12 -05:00
case LEGACY_LOGRADIO_UUID :
2024-07-02 08:04:09 -05:00
Logger . services . info ( " ✅ [BLE] did discover legacy LOGRADIO (Notify) characteristic for Meshtastic by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
LEGACY_LOGRADIO_characteristic = characteristic
peripheral . setNotifyValue ( true , for : characteristic )
2024-07-10 16:03:38 -05:00
2024-06-23 07:09:14 -07:00
case LOGRADIO_UUID :
2024-06-23 13:08:15 -07:00
Logger . services . info ( " ✅ [BLE] did discover LOGRADIO (Notify) characteristic for Meshtastic by \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2024-06-23 07:09:14 -07:00
LOGRADIO_characteristic = characteristic
peripheral . setNotifyValue ( true , for : characteristic )
2024-07-10 16:03:38 -05:00
2021-11-29 16:51:59 -08:00
default :
break
}
2022-06-01 23:23:02 -07:00
}
2023-03-06 10:33:18 -08:00
if ! [ FROMNUM_characteristic , TORADIO_characteristic ] . contains ( nil ) {
2023-10-17 20:35:29 -07:00
if mqttProxyConnected {
mqttManager . mqttClientProxy ? . disconnect ( )
}
2022-08-30 07:46:46 -05:00
sendWantConfig ( )
}
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2024-05-29 16:40:07 -05:00
// MARK: M q t t C l i e n t P r o x y M a n a g e r D e l e g a t e M e t h o d s
2023-08-16 18:28:55 -07:00
func onMqttConnected ( ) {
mqttProxyConnected = true
2024-04-05 17:14:04 -07:00
mqttError = " "
2024-06-23 13:08:15 -07:00
Logger . services . info ( " 📲 [MQTT Client Proxy] onMqttConnected now subscribing to \( self . mqttManager . topic , privacy : . public ) . " )
2023-08-16 18:28:55 -07:00
mqttManager . mqttClientProxy ? . subscribe ( mqttManager . topic )
}
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
func onMqttDisconnected ( ) {
mqttProxyConnected = false
2024-06-23 16:11:02 -07:00
Logger . services . info ( " 📲 MQTT Disconnected " )
2023-08-16 18:28:55 -07:00
}
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
func onMqttMessageReceived ( message : CocoaMQTTMessage ) {
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
if message . topic . contains ( " /stat/ " ) {
return
}
var proxyMessage = MqttClientProxyMessage ( )
proxyMessage . topic = message . topic
proxyMessage . data = Data ( message . payload )
proxyMessage . retained = message . retained
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . mqttClientProxyMessage = proxyMessage
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return
}
2023-08-16 18:28:55 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
}
}
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
func onMqttError ( message : String ) {
mqttProxyConnected = false
2024-04-05 17:14:04 -07:00
mqttError = message
2024-06-23 13:08:15 -07:00
Logger . services . info ( " 📲 [MQTT Client Proxy] onMqttError: \( message , privacy : . public ) " )
2023-08-16 18:28:55 -07:00
}
2024-07-10 16:03:38 -05:00
2023-08-16 18:28:55 -07:00
// MARK: P r o t o b u f M e t h o d s
2023-01-19 22:04:18 -08:00
func requestDeviceMetadata ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 , context : NSManagedObjectContext ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-08-09 23:36:00 -07:00
guard connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected else { return 0 }
2024-07-10 16:03:38 -05:00
2022-09-27 06:33:00 -07:00
var adminPacket = AdminMessage ( )
2022-10-09 18:32:21 -07:00
adminPacket . getDeviceMetadataRequest = true
2022-09-27 06:33:00 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
2023-01-19 22:04:18 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
2022-09-27 06:33:00 -07:00
meshPacket . priority = MeshPacket . Priority . reliable
2023-01-19 22:04:18 -08:00
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2022-09-27 06:33:00 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
meshPacket . decoded = dataMessage
} else {
return 0
}
2024-07-10 16:03:38 -05:00
2024-06-23 13:08:15 -07:00
let messageDescription = " 🛎️ [Device Metadata] Requested for node \( toUser . longName ? ? " unknown " . localized ) by \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-19 00:16:48 -08:00
return Int64 ( meshPacket . id )
}
return 0
2022-09-27 06:33:00 -07:00
}
2024-07-10 16:03:38 -05:00
2023-03-06 10:33:18 -08:00
func sendTraceRouteRequest ( destNum : Int64 , wantResponse : Bool ) -> Bool {
2024-07-10 16:03:38 -05:00
2022-12-27 17:44:27 -08:00
var success = false
2023-08-09 23:36:00 -07:00
guard connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected else { return success }
2024-07-10 16:03:38 -05:00
2023-02-02 23:17:23 -08:00
let fromNodeNum = connectedPeripheral . num
2022-12-27 17:44:27 -08:00
let routePacket = RouteDiscovery ( )
var meshPacket = MeshPacket ( )
2023-12-08 11:41:29 -08:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
2022-12-27 17:44:27 -08:00
meshPacket . to = UInt32 ( destNum )
2023-02-02 23:17:23 -08:00
meshPacket . from = UInt32 ( fromNodeNum )
meshPacket . wantAck = true
2022-12-27 17:44:27 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? routePacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . tracerouteApp
dataMessage . wantResponse = true
meshPacket . decoded = dataMessage
} else {
return false
}
2022-12-27 17:44:27 -08:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-12-27 17:44:27 -08:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
success = true
2024-07-10 16:03:38 -05:00
let traceRoute = TraceRouteEntity ( context : context )
2024-06-28 08:50:49 -05:00
let nodes = NodeInfoEntity . fetchRequest ( )
2023-12-08 11:41:29 -08:00
nodes . predicate = NSPredicate ( format : " num IN %@ " , [ destNum , self . connectedPeripheral . num ] )
do {
2024-07-10 16:03:38 -05:00
let fetchedNodes = try context . fetch ( nodes )
2023-12-08 11:41:29 -08:00
let receivingNode = fetchedNodes . first ( where : { $0 . num = = destNum } )
let connectedNode = fetchedNodes . first ( where : { $0 . num = = self . connectedPeripheral . num } )
traceRoute . id = Int64 ( meshPacket . id )
traceRoute . time = Date ( )
traceRoute . node = receivingNode
// G r a b t h e m o s t r e c e n t p o s t i o n , w i t h i n t h e l a s t h o u r
2024-05-29 16:40:07 -05:00
if connectedNode ? . positions ? . count ? ? 0 > 0 , let mostRecent = connectedNode ? . positions ? . lastObject as ? PositionEntity {
2024-04-08 08:21:37 -07:00
if mostRecent . time ! >= Calendar . current . date ( byAdding : . hour , value : - 24 , to : Date ( ) ) ! {
2023-12-08 11:41:29 -08:00
traceRoute . altitude = mostRecent . altitude
traceRoute . latitudeI = mostRecent . latitudeI
traceRoute . longitudeI = mostRecent . longitudeI
2023-12-21 12:30:04 -08:00
traceRoute . hasPositions = true
2023-12-08 11:41:29 -08:00
}
}
do {
2024-07-10 16:03:38 -05:00
try context . save ( )
2024-06-23 16:11:02 -07:00
Logger . data . info ( " 💾 Saved TraceRoute sent to node: \( String ( receivingNode ? . user ? . longName ? ? " unknown " . localized ) , privacy : . public ) " )
2023-12-08 11:41:29 -08:00
} catch {
2024-07-10 16:03:38 -05:00
context . rollback ( )
2023-12-08 11:41:29 -08:00
let nsError = error as NSError
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Error Updating Core Data BluetoothConfigEntity: \( nsError , privacy : . public ) " )
2023-12-08 11:41:29 -08:00
}
2024-07-10 16:03:38 -05:00
2024-06-23 16:11:02 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.traceroute.sent %@ " . localized , destNum . toHex ( ) )
2023-12-08 11:41:29 -08:00
MeshLogger . log ( " 🪧 \( logString ) " )
2024-07-10 16:03:38 -05:00
2023-12-08 11:41:29 -08:00
} catch {
2024-07-10 16:03:38 -05:00
2023-12-08 11:41:29 -08:00
}
2022-12-27 17:44:27 -08:00
}
return success
}
2024-07-10 16:03:38 -05:00
2022-08-30 07:57:15 -05:00
func sendWantConfig ( ) {
2023-08-09 23:36:00 -07:00
guard connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected else { return }
2024-07-10 16:03:38 -05:00
2022-10-11 14:25:59 -07:00
if FROMRADIO_characteristic = = nil {
2023-05-05 09:27:24 -07:00
MeshLogger . log ( " 🚨 \( " firmware.version.unsupported " . localized ) " )
2022-10-11 14:25:59 -07:00
invalidVersion = true
return
} else {
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let nodeName = connectedPeripheral ? . peripheral . name ? ? " unknown " . localized
let logString = String . localizedStringWithFormat ( " mesh.log.wantconfig %@ " . localized , nodeName )
2023-03-28 14:52:11 -07:00
MeshLogger . log ( " 🛎️ \( logString ) " )
// B L E C h a r a c t e r i s t i c s d i s c o v e r e d , i s s u e w a n t C o n f i g
var toRadio : ToRadio = ToRadio ( )
configNonce += 1
toRadio . wantConfigID = configNonce
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return
}
2023-03-28 14:52:11 -07:00
connectedPeripheral ! . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2022-10-11 14:25:59 -07:00
// E i t h e r R e a d t h e c o n f i g c o m p l e t e v a l u e o r f r o m n u m n o t i f y v a l u e
2023-12-20 19:34:35 -08:00
guard connectedPeripheral != nil else { return }
2022-10-11 14:25:59 -07:00
connectedPeripheral ! . peripheral . readValue ( for : FROMRADIO_characteristic )
}
2022-08-30 07:46:46 -05:00
}
2024-07-10 16:03:38 -05:00
2021-10-27 20:31:20 -07:00
func peripheral ( _ peripheral : CBPeripheral , didUpdateNotificationStateFor characteristic : CBCharacteristic , error : Error ? ) {
2024-06-23 12:25:08 -07:00
if let error {
2024-06-25 08:29:26 -07:00
Logger . services . error ( " 💥 [BLE] didUpdateNotificationStateFor error: \( characteristic . uuid , privacy : . public ) \( error . localizedDescription , privacy : . public ) " )
2024-06-23 12:25:08 -07:00
} else {
2024-06-25 08:29:26 -07:00
Logger . services . info ( " ℹ ️ [BLE] peripheral didUpdateNotificationStateFor \( characteristic . uuid , privacy : . public ) " )
2024-06-23 12:25:08 -07:00
}
2021-10-27 20:31:20 -07:00
}
2024-07-10 16:03:38 -05:00
2024-07-02 13:13:12 -05:00
fileprivate func handleRadioLog ( radioLog : String ) {
var log = radioLog
// / D e b u g L o g L e v e l
if log . starts ( with : " DEBUG | " ) {
do {
let logString = log
if let coordsMatch = try CommonRegex . COORDS_REGEX . firstMatch ( in : logString ) {
log = " \( log . replacingOccurrences ( of : " DEBUG | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) ) "
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . debug ( " 🛰️ \( log . prefix ( upTo : coordsMatch . range . lowerBound ) , privacy : . public ) \( coordsMatch . 0. replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression ) , privacy : . private ) \( log . suffix ( from : coordsMatch . range . upperBound ) , privacy : . public ) " )
} else {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . debug ( " 🕵🏻♂️ \( log . replacingOccurrences ( of : " DEBUG | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
}
} catch {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . debug ( " 🕵🏻♂️ \( log . replacingOccurrences ( of : " DEBUG | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
}
} else if log . starts ( with : " INFO | " ) {
do {
let logString = log
if let coordsMatch = try CommonRegex . COORDS_REGEX . firstMatch ( in : logString ) {
log = " \( log . replacingOccurrences ( of : " INFO | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) ) "
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . info ( " 🛰️ \( log . prefix ( upTo : coordsMatch . range . lowerBound ) , privacy : . public ) \( coordsMatch . 0. replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression ) , privacy : . private ) \( log . suffix ( from : coordsMatch . range . upperBound ) , privacy : . public ) " )
} else {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . info ( " 📢 \( log . replacingOccurrences ( of : " INFO | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
}
} catch {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . info ( " 📢 \( log . replacingOccurrences ( of : " INFO | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
}
} else if log . starts ( with : " WARN | " ) {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . warning ( " ⚠️ \( log . replacingOccurrences ( of : " WARN | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
} else if log . starts ( with : " ERROR | " ) {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . error ( " 💥 \( log . replacingOccurrences ( of : " ERROR | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
} else if log . starts ( with : " CRIT | " ) {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . critical ( " 🧨 \( log . replacingOccurrences ( of : " CRIT | " , with : " " ) . trimmingCharacters ( in : . whitespaces ) , privacy : . public ) " )
} else {
log = log . replacingOccurrences ( of : " [,] " , with : " " , options : . regularExpression )
Logger . radio . debug ( " 📟 \( log , privacy : . public ) " )
}
}
2022-09-28 15:50:35 -07:00
func peripheral ( _ peripheral : CBPeripheral , didUpdateValueFor characteristic : CBCharacteristic , error : Error ? ) {
2024-07-10 16:03:38 -05:00
2024-05-31 16:42:34 -05:00
if let error {
2024-07-10 16:03:38 -05:00
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚫 [BLE] didUpdateValueFor Characteristic error \( error . localizedDescription , privacy : . public ) " )
2024-05-31 16:42:34 -05:00
let errorCode = ( error as NSError ) . code
2022-12-30 01:52:33 -08:00
if errorCode = = 5 || errorCode = = 15 {
// B L E P I N c o n n e c t i o n e r r o r s
// 5 C B A T T E r r o r D o m a i n C o d e = 5 " A u t h e n t i c a t i o n i s i n s u f f i c i e n t . "
// 1 5 C B A T T E r r o r D o m a i n C o d e = 1 5 " E n c r y p t i o n i s i n s u f f i c i e n t . "
2024-05-31 16:42:34 -05:00
lastConnectionError = " 🚨 " + String . localizedStringWithFormat ( " ble.errorcode.pin %@ " . localized , error . localizedDescription )
2024-06-25 08:29:26 -07:00
Logger . services . error ( " 🚫 [BLE] \( error . localizedDescription , privacy : . public ) Please try connecting again and check the PIN carefully. " )
2023-01-03 21:45:10 -08:00
self . disconnectPeripheral ( reconnect : false )
2022-01-13 18:18:24 -08:00
}
2024-04-13 09:46:13 -07:00
return
2022-09-28 15:50:35 -07:00
}
2024-07-10 16:03:38 -05:00
2022-09-28 15:50:35 -07:00
switch characteristic . uuid {
2024-06-23 07:09:14 -07:00
case LOGRADIO_UUID :
2024-06-23 16:11:02 -07:00
if characteristic . value = = nil || characteristic . value ! . isEmpty {
2024-06-23 07:09:14 -07:00
return
}
2024-07-02 13:13:12 -05:00
do {
let logRecord = try LogRecord ( serializedData : characteristic . value ! )
var message = logRecord . source . isEmpty ? logRecord . message : " [ \( logRecord . source ) ] \( logRecord . message ) "
switch logRecord . level {
case . debug :
message = " DEBUG | \( message ) "
case . info :
message = " INFO | \( message ) "
case . warning :
2024-07-10 16:03:38 -05:00
message = " WARN | \( message ) "
2024-07-02 13:13:12 -05:00
case . error :
2024-07-10 16:03:38 -05:00
message = " ERROR | \( message ) "
2024-07-02 13:13:12 -05:00
case . critical :
2024-07-10 16:03:38 -05:00
message = " CRIT | \( message ) "
2024-07-02 13:13:12 -05:00
default :
message = " DEBUG | \( message ) "
2024-06-23 07:09:14 -07:00
}
2024-07-02 13:13:12 -05:00
handleRadioLog ( radioLog : message )
2024-06-23 07:09:14 -07:00
}
2024-07-02 13:13:12 -05:00
catch {
// I g n o r e f a i l t o p a r s e a s L o g R e c o r d
}
2024-07-10 16:03:38 -05:00
2024-07-02 13:13:12 -05:00
case LEGACY_LOGRADIO_UUID :
if characteristic . value = = nil || characteristic . value ! . isEmpty {
return
}
if let log = String ( data : characteristic . value ! , encoding : . utf8 ) {
handleRadioLog ( radioLog : log )
2024-06-23 07:09:14 -07:00
}
2024-07-10 16:03:38 -05:00
2021-11-29 17:09:27 -08:00
case FROMRADIO_UUID :
2024-07-10 16:03:38 -05:00
2021-11-29 17:09:27 -08:00
if characteristic . value = = nil || characteristic . value ! . isEmpty {
return
}
var decodedInfo = FromRadio ( )
2024-07-10 16:03:38 -05:00
2022-06-24 07:48:25 -07:00
do {
decodedInfo = try FromRadio ( serializedData : characteristic . value ! )
2024-07-10 16:03:38 -05:00
2022-06-24 07:48:25 -07:00
} catch {
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 💥 \( error . localizedDescription , privacy : . public ) \( characteristic . value ! , privacy : . public ) " )
2022-06-24 07:48:25 -07:00
}
2024-07-10 16:03:38 -05:00
2023-08-08 18:10:50 -07:00
// P u b l i s h m q t t C l i e n t P r o x y M e s s a g e s r e c e i v e d o n t h e f r o m r a d i o
2023-08-07 16:25:01 -07:00
if decodedInfo . payloadVariant = = FromRadio . OneOf_PayloadVariant . mqttClientProxyMessage ( decodedInfo . mqttClientProxyMessage ) {
2024-05-29 16:40:07 -05:00
let message = CocoaMQTTMessage (
2023-08-07 16:25:01 -07:00
topic : decodedInfo . mqttClientProxyMessage . topic ,
2024-05-29 16:40:07 -05:00
payload : [ UInt8 ] ( decodedInfo . mqttClientProxyMessage . data ) ,
2023-08-07 16:25:01 -07:00
retained : decodedInfo . mqttClientProxyMessage . retained
)
2023-08-09 22:51:26 -07:00
mqttManager . mqttClientProxy ? . publish ( message )
2023-08-07 16:25:01 -07:00
}
2024-07-10 16:03:38 -05:00
2022-05-27 19:18:33 -07:00
switch decodedInfo . packet . decoded . portnum {
2024-07-10 16:03:38 -05:00
2023-03-28 14:52:11 -07:00
// H a n d l e A n y l o c a l o n l y p a c k e t s w e g e t o v e r B L E
2023-03-06 13:26:04 -08:00
case . unknownApp :
2022-07-02 10:06:50 -07:00
var nowKnown = false
2022-12-30 01:52:33 -08:00
// M y I n f o f r o m i n i t i a l c o n n e c t i o n
2024-05-04 08:20:53 -07:00
if decodedInfo . myInfo . isInitialized && decodedInfo . myInfo . myNodeNum > 0 {
2024-07-10 16:03:38 -05:00
let myInfo = updateCoreDataController . myInfoPacket ( myInfo : decodedInfo . myInfo , peripheralId : self . connectedPeripheral . id )
2023-07-26 07:03:56 -05:00
if myInfo != nil {
2024-04-19 13:36:17 -07:00
UserDefaults . preferredPeripheralNum = Int ( myInfo ? . myNodeNum ? ? 0 )
connectedPeripheral . num = myInfo ? . myNodeNum ? ? 0
2023-07-26 07:03:56 -05:00
connectedPeripheral . name = myInfo ? . bleName ? ? " unknown " . localized
connectedPeripheral . longName = myInfo ? . bleName ? ? " unknown " . localized
2024-06-23 13:00:20 -07:00
let newConnection = Int64 ( UserDefaults . preferredPeripheralNum ) != Int64 ( decodedInfo . myInfo . myNodeNum )
if newConnection {
let container = NSPersistentContainer ( name : " Meshtastic " )
if let url = FileManager . default . urls ( for : . documentDirectory , in : . userDomainMask ) . first {
let databasePath = url . appendingPathComponent ( " backup " )
. appendingPathComponent ( " \( UserDefaults . preferredPeripheralNum ) " )
. appendingPathComponent ( " Meshtastic.sqlite " )
if FileManager . default . fileExists ( atPath : databasePath . path ) {
do {
disconnectPeripheral ( reconnect : false )
try container . restorePersistentStore ( from : databasePath )
2024-07-10 16:03:38 -05:00
context . refreshAllObjects ( )
2024-06-26 15:12:24 -07:00
let request = MyInfoEntity . fetchRequest ( )
2024-07-10 16:03:38 -05:00
try context . fetch ( request )
2024-06-23 13:00:20 -07:00
UserDefaults . preferredPeripheralNum = Int ( myInfo ? . myNodeNum ? ? 0 )
connectTo ( peripheral : peripheral )
2024-06-23 16:11:02 -07:00
Logger . data . notice ( " 🗂️ Restored Core data for / \( UserDefaults . preferredPeripheralNum , privacy : . public ) " )
2024-06-23 13:00:20 -07:00
} catch {
2024-06-23 16:11:02 -07:00
Logger . data . error ( " 🗂️ Restore Core data copy error: \( error , privacy : . public ) " )
2024-06-23 13:00:20 -07:00
}
}
}
}
2022-07-02 10:06:50 -07:00
}
2024-02-24 22:33:11 -08:00
tryClearExistingChannels ( )
2022-07-02 10:06:50 -07:00
}
// N o d e I n f o
2024-05-04 08:20:53 -07:00
if decodedInfo . nodeInfo . num > 0 {
2022-07-02 10:06:50 -07:00
nowKnown = true
2024-07-10 16:03:38 -05:00
if let nodeInfo = updateCoreDataController . nodeInfoPacket ( nodeInfo : decodedInfo . nodeInfo , channel : decodedInfo . packet . channel ) {
2024-05-04 20:59:16 -07:00
if self . connectedPeripheral != nil && self . connectedPeripheral . num = = nodeInfo . num {
if nodeInfo . user != nil {
connectedPeripheral . shortName = nodeInfo . user ? . shortName ? ? " ? "
connectedPeripheral . longName = nodeInfo . user ? . longName ? ? " unknown " . localized
2022-06-01 23:23:02 -07:00
}
}
}
2022-07-02 10:06:50 -07:00
}
2022-10-09 18:32:21 -07:00
// C h a n n e l s
2024-05-04 08:20:53 -07:00
if decodedInfo . channel . isInitialized && connectedPeripheral != nil {
2022-10-09 18:32:21 -07:00
nowKnown = true
2024-07-10 16:03:38 -05:00
updateCoreDataController . channelPacket ( channel : decodedInfo . channel , fromNum : Int64 ( truncatingIfNeeded : connectedPeripheral . num ) )
2022-10-09 18:32:21 -07:00
}
2022-07-02 10:06:50 -07:00
// C o n f i g
2024-05-04 08:20:53 -07:00
if decodedInfo . config . isInitialized && ! invalidVersion && connectedPeripheral != nil {
2022-07-02 10:06:50 -07:00
nowKnown = true
2024-07-10 16:03:38 -05:00
updateCoreDataController . localConfig ( config : decodedInfo . config , context : context , nodeNum : Int64 ( truncatingIfNeeded : self . connectedPeripheral . num ) , nodeLongName : self . connectedPeripheral . longName )
2022-07-02 10:06:50 -07:00
}
// M o d u l e C o n f i g
2024-05-29 16:40:07 -05:00
if decodedInfo . moduleConfig . isInitialized && ! invalidVersion && self . connectedPeripheral ? . num != 0 {
2022-07-02 10:06:50 -07:00
nowKnown = true
2024-07-10 16:03:38 -05:00
updateCoreDataController . moduleConfig ( config : decodedInfo . moduleConfig , context : context , nodeNum : Int64 ( truncatingIfNeeded : self . connectedPeripheral ? . num ? ? 0 ) , nodeLongName : self . connectedPeripheral . longName )
2022-10-03 16:52:00 -07:00
if decodedInfo . moduleConfig . payloadVariant = = ModuleConfig . OneOf_PayloadVariant . cannedMessage ( decodedInfo . moduleConfig . cannedMessage ) {
2022-11-26 10:13:46 -08:00
if decodedInfo . moduleConfig . cannedMessage . enabled {
2022-12-12 21:19:22 -08:00
_ = self . getCannedMessageModuleMessages ( destNum : self . connectedPeripheral . num , wantResponse : true )
2022-11-26 10:13:46 -08:00
}
2022-10-03 16:52:00 -07:00
}
2022-07-02 10:06:50 -07:00
}
2023-02-17 10:35:37 -08:00
// D e v i c e M e t a d a t a
2024-05-04 08:20:53 -07:00
if decodedInfo . metadata . firmwareVersion . count > 0 && ! invalidVersion {
2023-02-17 10:35:37 -08:00
nowKnown = true
2024-07-10 16:03:38 -05:00
updateCoreDataController . deviceMetadataPacket ( metadata : decodedInfo . metadata , fromNum : connectedPeripheral . num )
2023-08-20 07:59:15 -05:00
connectedPeripheral . firmwareVersion = decodedInfo . metadata . firmwareVersion
2023-07-26 07:03:56 -05:00
let lastDotIndex = decodedInfo . metadata . firmwareVersion . lastIndex ( of : " . " )
if lastDotIndex = = nil {
invalidVersion = true
connectedVersion = " 0.0.0 "
} else {
let version = decodedInfo . metadata . firmwareVersion [ . . . ( lastDotIndex ? ? String . Index ( utf16Offset : 6 , in : decodedInfo . metadata . firmwareVersion ) ) ]
nowKnown = true
connectedVersion = String ( version . dropLast ( ) )
2023-09-04 20:17:09 -07:00
appState . firmwareVersion = connectedVersion
2024-03-10 20:17:54 -07:00
UserDefaults . firmwareVersion = connectedVersion
2023-07-26 07:03:56 -05:00
}
let supportedVersion = connectedVersion = = " 0.0.0 " || self . minimumVersion . compare ( connectedVersion , options : . numeric ) = = . orderedAscending || minimumVersion . compare ( connectedVersion , options : . numeric ) = = . orderedSame
if ! supportedVersion {
invalidVersion = true
lastConnectionError = " 🚨 " + " update.firmware " . localized
return
}
2023-02-17 10:35:37 -08:00
}
2022-07-02 10:06:50 -07:00
// L o g a n y o t h e r u n k n o w n A p p c a l l s
2023-03-06 13:26:04 -08:00
if ! nowKnown { MeshLogger . log ( " 🕸️ MESH PACKET received for Unknown App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " ) }
2023-08-18 13:31:24 -05:00
case . textMessageApp , . detectionSensorApp :
2024-07-10 16:03:38 -05:00
updateCoreDataController . textMessageAppPacket ( packet : decodedInfo . packet , wantRangeTestPackets : wantRangeTestPackets , connectedNode : ( self . connectedPeripheral != nil ? connectedPeripheral . num : 0 ) )
2023-03-06 13:26:04 -08:00
case . remoteHardwareApp :
MeshLogger . log ( " 🕸️ MESH PACKET received for Remote Hardware App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " )
case . positionApp :
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertPositionPacket ( packet : decodedInfo . packet )
2023-03-06 13:26:04 -08:00
case . waypointApp :
2024-07-10 16:03:38 -05:00
updateCoreDataController . waypointPacket ( packet : decodedInfo . packet )
2023-03-06 13:26:04 -08:00
case . nodeinfoApp :
2024-07-10 16:03:38 -05:00
if ! invalidVersion {
updateCoreDataController . upsertNodeInfoPacket ( packet : decodedInfo . packet )
}
2023-03-06 13:26:04 -08:00
case . routingApp :
2024-07-10 16:03:38 -05:00
if ! invalidVersion { updateCoreDataController . routingPacket ( packet : decodedInfo . packet , connectedNodeNum : self . connectedPeripheral . num ) }
2023-03-06 13:26:04 -08:00
case . adminApp :
2024-07-10 16:03:38 -05:00
updateCoreDataController . adminAppPacket ( packet : decodedInfo . packet )
2023-03-06 13:26:04 -08:00
case . replyApp :
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Reply App handling as a text message " )
2024-07-10 16:03:38 -05:00
updateCoreDataController . textMessageAppPacket ( packet : decodedInfo . packet , wantRangeTestPackets : wantRangeTestPackets , connectedNode : ( self . connectedPeripheral != nil ? connectedPeripheral . num : 0 ) )
2023-03-06 13:26:04 -08:00
case . ipTunnelApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r I P T u n n e l A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for IP Tunnel App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . serialApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r S e r i a l A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Serial App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . storeForwardApp :
2024-07-10 16:03:38 -05:00
if let connectedPeripheral , wantStoreAndForwardPackets {
storeAndForwardPacket ( packet : decodedInfo . packet , connectedNodeNum : connectedPeripheral . num , context : context )
2023-12-10 12:38:01 -08:00
} else {
MeshLogger . log ( " 🕸️ MESH PACKET received for Store and Forward App - Store and Forward is disabled. " )
}
2023-03-06 13:26:04 -08:00
case . rangeTestApp :
2024-01-28 09:36:19 -08:00
if wantRangeTestPackets {
2024-07-10 16:03:38 -05:00
updateCoreDataController . textMessageAppPacket ( packet : decodedInfo . packet , wantRangeTestPackets : true , connectedNode : ( self . connectedPeripheral != nil ? connectedPeripheral . num : 0 ) )
2024-05-29 16:40:07 -05:00
} else {
2023-12-10 12:38:01 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Range Test App Range testing is disabled. " )
2023-08-19 19:38:01 -05:00
}
2023-03-06 13:26:04 -08:00
case . telemetryApp :
2024-07-10 16:03:38 -05:00
if ! invalidVersion {
updateCoreDataController . telemetryPacket ( packet : decodedInfo . packet , connectedNode : ( self . connectedPeripheral != nil ? connectedPeripheral . num : 0 ) )
}
2023-03-06 13:26:04 -08:00
case . textMessageCompressedApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r T e x t M e s s a g e C o m p r e s s e d A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Text Message Compressed App UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . zpsApp :
2024-03-02 08:31:29 -08:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r Z e r o P o s i t i o n i n g S y s t e m A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
MeshLogger . log ( " 🕸️ MESH PACKET received for Zero Positioning System App UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . privateApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r P r i v a t e A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Private App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . atakForwarder :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r A T A K F o r w a r d e r A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for ATAK Forwarder App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . simulatorApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r S i m u l a t o r A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Simulator App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . audioApp :
2024-05-29 16:40:07 -05:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r A u d i o A p p U N H A N D L E D \ ( ( t r y ? d e c o d e d I n f o . p a c k e t . j s o n S t r i n g ( ) ) ? ? " J S O N D e c o d e F a i l u r e " ) " )
2024-03-02 08:31:29 -08:00
MeshLogger . log ( " 🕸️ MESH PACKET received for Audio App UNHANDLED UNHANDLED " )
2023-03-06 13:26:04 -08:00
case . tracerouteApp :
2023-03-28 14:52:11 -07:00
if let routingMessage = try ? RouteDiscovery ( serializedData : decodedInfo . packet . decoded . payload ) {
2024-07-10 16:03:38 -05:00
let traceRoute = queryCoreDataController . getTraceRoute ( id : Int64 ( decodedInfo . packet . decoded . requestID ) )
2023-12-08 11:41:29 -08:00
traceRoute ? . response = true
traceRoute ? . route = routingMessage . route
2023-03-28 14:52:11 -07:00
if routingMessage . route . count = = 0 {
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.traceroute.received.direct %@ " . localized , String ( decodedInfo . packet . from ) )
2023-03-28 14:52:11 -07:00
MeshLogger . log ( " 🪧 \( logString ) " )
2024-07-10 16:03:38 -05:00
2023-12-08 11:41:29 -08:00
} else {
var routeString = " You --> "
var hopNodes : [ TraceRouteHopEntity ] = [ ]
2023-12-21 09:03:24 -08:00
for node in routingMessage . route {
2024-07-10 16:03:38 -05:00
var hopNode = queryCoreDataController . getNodeInfo ( id : Int64 ( node ) )
2024-02-27 11:26:26 -08:00
if hopNode = = nil && hopNode ? . num ? ? 0 > 0 {
2024-07-10 16:03:38 -05:00
hopNode = createNodeInfo ( num : Int64 ( node ) , context : context )
2024-01-16 08:55:23 -08:00
}
2024-07-10 16:03:38 -05:00
let traceRouteHop = TraceRouteHopEntity ( context : context )
2023-12-21 09:03:24 -08:00
traceRouteHop . time = Date ( )
if hopNode ? . hasPositions ? ? false {
2024-02-20 18:50:49 -08:00
traceRoute ? . hasPositions = true
2024-05-29 16:40:07 -05:00
if let mostRecent = hopNode ? . positions ? . lastObject as ? PositionEntity , mostRecent . time ! >= Calendar . current . date ( byAdding : . minute , value : - 60 , to : Date ( ) ) ! {
2023-12-21 09:03:24 -08:00
traceRouteHop . altitude = mostRecent . altitude
traceRouteHop . latitudeI = mostRecent . latitudeI
traceRouteHop . longitudeI = mostRecent . longitudeI
traceRouteHop . name = hopNode ? . user ? . longName ? ? " unknown " . localized
2023-12-21 12:30:04 -08:00
} else {
traceRoute ? . hasPositions = false
2023-12-21 09:03:24 -08:00
}
2023-12-21 12:30:04 -08:00
} else {
traceRoute ? . hasPositions = false
2023-12-21 09:03:24 -08:00
}
traceRouteHop . num = hopNode ? . num ? ? 0
if hopNode != nil {
2024-04-12 16:34:28 -07:00
if decodedInfo . packet . rxTime > 0 {
hopNode ? . lastHeard = Date ( timeIntervalSince1970 : TimeInterval ( Int64 ( decodedInfo . packet . rxTime ) ) )
}
2023-12-21 09:03:24 -08:00
hopNodes . append ( traceRouteHop )
}
2024-02-27 21:16:44 -08:00
routeString += " \( hopNode ? . user ? . longName ? ? " unknown " . localized ) \( hopNode ? . viaMqtt ? ? false ? " MQTT " : " " ) --> "
2023-12-21 09:03:24 -08:00
}
2023-12-21 10:59:09 -08:00
routeString += traceRoute ? . node ? . user ? . longName ? ? " unknown " . localized
2023-12-08 11:41:29 -08:00
traceRoute ? . routeText = routeString
traceRoute ? . hops = NSOrderedSet ( array : hopNodes )
do {
2024-07-10 16:03:38 -05:00
try context . save ( )
2024-06-03 02:17:55 -07:00
Logger . data . info ( " 💾 Saved Trace Route " )
2023-12-08 11:41:29 -08:00
} catch {
2024-07-10 16:03:38 -05:00
context . rollback ( )
2023-12-08 11:41:29 -08:00
let nsError = error as NSError
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Error Updating Core Data TraceRouteHOp: \( nsError , privacy : . public ) " )
2022-12-27 17:44:27 -08:00
}
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.traceroute.received.route %@ " . localized , routeString )
2023-03-28 14:52:11 -07:00
MeshLogger . log ( " 🪧 \( logString ) " )
2022-12-27 17:44:27 -08:00
}
2023-03-28 14:52:11 -07:00
}
2023-05-04 20:11:42 -07:00
case . neighborinfoApp :
2023-11-26 10:45:03 -08:00
if let neighborInfo = try ? NeighborInfo ( serializedData : decodedInfo . packet . decoded . payload ) {
2024-06-02 20:13:40 -07:00
// M e s h L o g g e r . l o g ( " 🕸 ️ M E S H P A C K E T r e c e i v e d f o r N e i g h b o r I n f o A p p U N H A N D L E D " )
MeshLogger . log ( " 🕸️ MESH PACKET received for Neighbor Info App UNHANDLED \( neighborInfo ) " )
2023-11-26 10:45:03 -08:00
}
2024-01-14 11:46:31 -08:00
case . paxcounterApp :
2024-07-10 16:03:38 -05:00
updateCoreDataController . paxCounterPacket ( packet : decodedInfo . packet )
2024-03-14 00:04:35 -07:00
case . mapReportApp :
2024-06-02 20:13:40 -07:00
MeshLogger . log ( " 🕸️ MESH PACKET received Map Report App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " )
2023-03-06 13:26:04 -08:00
case . UNRECOGNIZED :
2024-06-02 20:13:40 -07:00
MeshLogger . log ( " 🕸️ MESH PACKET received UNRECOGNIZED App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " )
2023-03-06 13:26:04 -08:00
case . max :
2024-06-03 02:17:55 -07:00
Logger . services . info ( " MAX PORT NUM OF 511 " )
2024-02-10 17:21:31 -08:00
case . atakPlugin :
MeshLogger . log ( " 🕸️ MESH PACKET received for ATAK Plugin App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " )
2024-07-07 14:39:10 -07:00
case . powerstressApp :
MeshLogger . log ( " 🕸️ MESH PACKET received for Power Stress App UNHANDLED \( ( try ? decodedInfo . packet . jsonString ( ) ) ? ? " JSON Decode Failure " ) " )
2022-05-27 19:18:33 -07:00
}
2024-07-10 16:03:38 -05:00
2022-06-11 09:50:25 -07:00
if decodedInfo . configCompleteID != 0 && decodedInfo . configCompleteID = = configNonce {
2022-10-22 07:45:07 -07:00
invalidVersion = false
lastConnectionError = " "
isSubscribed = true
2024-06-28 18:21:54 -07:00
Logger . mesh . info ( " 🤜 [BLE] Want Config Complete. ID: \( decodedInfo . configCompleteID ) " )
2021-12-18 01:01:56 -08:00
peripherals . removeAll ( where : { $0 . peripheral . state = = CBPeripheralState . disconnected } )
2022-05-27 19:34:42 -07:00
// C o n f i g c o n p l e t e r e t u r n s s o w e d o n ' t r e a d t h e c h a r a c t e r i s t i c a g a i n
2024-07-10 16:03:38 -05:00
2024-02-13 10:58:07 -08:00
// / M Q T T C l i e n t P r o x y a n d R a n g e T e s t a n d S t o r e a n d F o r w a r d i n t e r e s t
2023-08-06 20:59:39 -07:00
if connectedPeripheral . num > 0 {
2024-07-10 16:03:38 -05:00
2024-06-28 08:50:49 -05:00
let fetchNodeInfoRequest = NodeInfoEntity . fetchRequest ( )
2023-08-01 22:28:02 -07:00
fetchNodeInfoRequest . predicate = NSPredicate ( format : " num == %lld " , Int64 ( connectedPeripheral . num ) )
do {
2024-07-10 16:03:38 -05:00
let fetchedNodeInfo = try context . fetch ( fetchNodeInfoRequest )
2023-09-03 22:14:59 -07:00
if fetchedNodeInfo . count = = 1 {
2023-09-03 21:36:54 -07:00
// S u b s c r i b e t o M q t t C l i e n t P r o x y i f e n a b l e d
2023-09-03 22:14:59 -07:00
if fetchedNodeInfo [ 0 ] . mqttConfig != nil && fetchedNodeInfo [ 0 ] . mqttConfig ? . enabled ? ? false && fetchedNodeInfo [ 0 ] . mqttConfig ? . proxyToClientEnabled ? ? false {
2023-08-06 22:31:19 -07:00
mqttManager . connectFromConfigSettings ( node : fetchedNodeInfo [ 0 ] )
2023-09-03 22:14:59 -07:00
} else {
if mqttProxyConnected {
mqttManager . mqttClientProxy ? . disconnect ( )
}
2023-08-06 20:59:39 -07:00
}
2023-09-03 21:36:54 -07:00
// S e t i n i t i a l u n r e a d m e s s a g e b a d g e s t a t e s
2023-09-03 22:14:59 -07:00
let appState = AppState . shared
2023-09-03 21:36:54 -07:00
appState . unreadChannelMessages = fetchedNodeInfo [ 0 ] . myInfo ? . unreadMessages ? ? 0
appState . unreadDirectMessages = fetchedNodeInfo [ 0 ] . user ? . unreadMessages ? ? 0
2024-05-29 16:40:07 -05:00
// a p p S t a t e . c o n n e c t e d N o d e = f e t c h e d N o d e I n f o [ 0 ]
2023-09-03 21:36:54 -07:00
UIApplication . shared . applicationIconBadgeNumber = appState . unreadChannelMessages + appState . unreadDirectMessages
2024-07-10 16:03:38 -05:00
2023-08-01 22:28:02 -07:00
}
2023-08-19 19:38:01 -05:00
if fetchedNodeInfo . count = = 1 && fetchedNodeInfo [ 0 ] . rangeTestConfig ? . enabled = = true {
2024-05-29 16:40:07 -05:00
wantRangeTestPackets = true
2023-08-19 19:38:01 -05:00
}
2023-12-10 12:38:01 -08:00
if fetchedNodeInfo . count = = 1 && fetchedNodeInfo [ 0 ] . storeForwardConfig ? . enabled = = true {
2024-05-29 16:40:07 -05:00
wantStoreAndForwardPackets = true
2023-12-10 12:38:01 -08:00
}
2024-07-10 16:03:38 -05:00
2023-08-01 22:28:02 -07:00
} catch {
2024-06-03 02:17:55 -07:00
Logger . data . error ( " Failed to find a node info for the connected node \( error . localizedDescription ) " )
2023-08-01 22:28:02 -07:00
}
}
2024-07-10 16:03:38 -05:00
2023-08-07 16:25:01 -07:00
// MARK: S h a r e L o c a t i o n P o s i t i o n U p d a t e T i m e r
// U s e c o n t e x t t o p a s s t h e r a d i o n a m e w i t h t h e t i m e r
// U s e a R u n L o o p t o p r e v e n t t h e t i m e r f r o m r u n n i n g o n t h e m a i n U I t h r e a d
if UserDefaults . provideLocation {
2024-01-08 13:51:13 -08:00
let interval = UserDefaults . provideLocationInterval >= 10 ? UserDefaults . provideLocationInterval : 30
positionTimer = Timer . scheduledTimer ( timeInterval : TimeInterval ( interval ) , target : self , selector : #selector ( positionTimerFired ) , userInfo : context , repeats : true )
2023-08-07 16:25:01 -07:00
if positionTimer != nil {
2024-01-08 13:51:13 -08:00
RunLoop . current . add ( positionTimer ! , forMode : . common )
2023-08-07 16:25:01 -07:00
}
}
2022-05-27 19:34:42 -07:00
return
2021-11-29 17:09:27 -08:00
}
2024-07-10 16:03:38 -05:00
2023-03-06 10:33:18 -08:00
case FROMNUM_UUID :
2024-06-23 18:25:22 -07:00
Logger . services . info ( " 🗞️ [BLE] (Notify) characteristic value will be read next " )
2021-11-29 17:09:27 -08:00
default :
2024-06-23 16:11:02 -07:00
Logger . services . error ( " 🚫 Unhandled Characteristic UUID: \( characteristic . uuid , privacy : . public ) " )
2022-09-28 15:50:35 -07:00
}
2022-11-02 06:02:58 -07:00
if FROMRADIO_characteristic != nil {
// E i t h e r R e a d t h e c o n f i g c o m p l e t e v a l u e o r f r o m n u m n o t i f y v a l u e
peripheral . readValue ( for : FROMRADIO_characteristic )
}
2022-05-27 19:18:33 -07:00
}
2024-07-10 16:03:38 -05:00
2022-11-07 18:51:17 -08:00
public func sendMessage ( message : String , toUserNum : Int64 , channel : Int32 , isEmoji : Bool , replyID : Int64 ) -> Bool {
2021-10-20 00:31:22 -07:00
var success = false
2024-07-10 16:03:38 -05:00
2021-10-20 00:31:22 -07:00
// R e t u r n f a l s e i f w e a r e n o t p r o p e r l y c o n n e c t e d t o a d e v i c e , h a n d l e r e t r y l o g i c i n t h e v i e w f o r n o w
if connectedPeripheral = = nil || connectedPeripheral ! . peripheral . state != CBPeripheralState . connected {
2024-07-10 16:03:38 -05:00
2021-11-21 13:48:28 -08:00
self . disconnectPeripheral ( )
2021-10-20 00:31:22 -07:00
self . startScanning ( )
2024-07-10 16:03:38 -05:00
2021-10-20 00:31:22 -07:00
// T r y a n d c o n n e c t t o t h e p r e f e r r e d P e r i p h e r i a l f i r s t
2023-08-18 00:12:59 -07:00
let preferredPeripheral = peripherals . filter ( { $0 . peripheral . identifier . uuidString = = UserDefaults . preferredPeripheralId as String } ) . first
2021-10-20 00:31:22 -07:00
if preferredPeripheral != nil && preferredPeripheral ? . peripheral != nil {
connectTo ( peripheral : preferredPeripheral ! . peripheral )
}
2023-05-05 09:27:24 -07:00
let nodeName = connectedPeripheral ? . peripheral . name ? ? " unknown " . localized
let logString = String . localizedStringWithFormat ( " mesh.log.textmessage.send.failed %@ " . localized , nodeName )
2023-01-01 14:48:50 -08:00
MeshLogger . log ( " 🚫 \( logString ) " )
2024-07-10 16:03:38 -05:00
2021-10-20 00:31:22 -07:00
success = false
2021-11-29 15:59:06 -08:00
} else if message . count < 1 {
2024-07-10 16:03:38 -05:00
2021-12-24 21:50:10 -08:00
// D o n ' t s e n d a n e m p t y m e s s a g e
2024-06-03 02:17:55 -07:00
Logger . mesh . info ( " 🚫 Don't Send an Empty Message " )
2021-10-20 00:31:22 -07:00
success = false
2024-07-10 16:03:38 -05:00
2021-11-29 15:59:06 -08:00
} else {
2021-12-25 23:48:12 -08:00
let fromUserNum : Int64 = self . connectedPeripheral . num
2024-07-10 16:03:38 -05:00
2024-06-28 08:50:49 -05:00
let messageUsers = UserEntity . fetchRequest ( )
2021-12-25 23:48:12 -08:00
messageUsers . predicate = NSPredicate ( format : " num IN %@ " , [ fromUserNum , Int64 ( toUserNum ) ] )
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
do {
2024-07-10 16:03:38 -05:00
2024-06-28 08:50:49 -05:00
let fetchedUsers = try context . fetch ( messageUsers )
2021-12-19 19:40:16 -08:00
if fetchedUsers . isEmpty {
2024-07-10 16:03:38 -05:00
2024-06-03 02:17:55 -07:00
Logger . data . error ( " 🚫 Message Users Not Found, Fail " )
2021-12-18 20:49:50 -08:00
success = false
2021-12-25 23:48:12 -08:00
} else if fetchedUsers . count >= 1 {
2024-07-10 16:03:38 -05:00
2024-06-28 08:50:49 -05:00
let newMessage = MessageEntity ( context : context )
2022-02-22 18:06:50 -10:00
newMessage . messageId = Int64 ( UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max ) )
2021-12-18 20:49:50 -08:00
newMessage . messageTimestamp = Int32 ( Date ( ) . timeIntervalSince1970 )
newMessage . receivedACK = false
2023-08-29 08:58:24 -07:00
newMessage . read = true
2022-11-08 11:30:08 -08:00
if toUserNum > 0 {
newMessage . toUser = fetchedUsers . first ( where : { $0 . num = = toUserNum } )
2023-08-29 08:48:28 -07:00
newMessage . toUser ? . lastMessage = Date ( )
2022-11-08 11:30:08 -08:00
}
2022-11-07 18:51:17 -08:00
newMessage . fromUser = fetchedUsers . first ( where : { $0 . num = = fromUserNum } )
2022-03-29 21:16:15 -07:00
newMessage . isEmoji = isEmoji
2022-07-02 10:06:50 -07:00
newMessage . admin = false
2022-11-07 18:51:17 -08:00
newMessage . channel = channel
2022-01-04 22:57:33 -08:00
if replyID > 0 {
newMessage . replyID = replyID
2022-01-01 22:55:25 -08:00
}
2021-12-18 20:49:50 -08:00
newMessage . messagePayload = message
2024-07-10 16:03:38 -05:00
newMessage . messagePayloadMarkdown = updateCoreDataController . generateMessageMarkdown ( message : message )
2023-09-03 09:04:07 -07:00
newMessage . read = true
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
let dataType = PortNum . textMessageApp
2023-02-11 07:47:49 -08:00
var messageQuotesReplaced = message . replacingOccurrences ( of : " ’ " , with : " ' " )
messageQuotesReplaced = message . replacingOccurrences ( of : " ” " , with : " \" " )
let payloadData : Data = messageQuotesReplaced . data ( using : String . Encoding . utf8 ) !
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
var dataMessage = DataMessage ( )
dataMessage . payload = payloadData
dataMessage . portnum = dataType
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
var meshPacket = MeshPacket ( )
2022-02-22 18:06:50 -10:00
meshPacket . id = UInt32 ( newMessage . messageId )
2022-11-08 11:30:08 -08:00
if toUserNum > 0 {
meshPacket . to = UInt32 ( toUserNum )
} else {
2024-02-05 23:31:54 -07:00
meshPacket . to = Self . emptyNodeNum
2022-11-08 11:30:08 -08:00
}
2022-11-08 12:48:16 -08:00
meshPacket . channel = UInt32 ( channel )
2021-12-19 19:40:16 -08:00
meshPacket . from = UInt32 ( fromUserNum )
2022-01-15 17:16:00 -08:00
meshPacket . decoded = dataMessage
2022-03-29 21:16:15 -07:00
meshPacket . decoded . emoji = isEmoji ? 1 : 0
2022-01-04 22:57:33 -08:00
if replyID > 0 {
2022-02-04 02:26:58 -08:00
meshPacket . decoded . replyID = UInt32 ( replyID )
2022-01-01 22:55:25 -08:00
}
2021-12-18 20:49:50 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2021-12-18 20:49:50 -08:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2024-06-23 16:11:02 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.textmessage.sent %@ %@ %@ " . localized , String ( newMessage . messageId ) , fromUserNum . toHex ( ) , toUserNum . toHex ( ) )
2024-07-10 16:03:38 -05:00
2023-01-01 14:48:50 -08:00
MeshLogger . log ( " 💬 \( logString ) " )
2021-12-18 20:49:50 -08:00
do {
2024-06-28 08:50:49 -05:00
try context . save ( )
2024-06-23 16:11:02 -07:00
Logger . data . info ( " 💾 Saved a new sent message from \( self . connectedPeripheral . num . toHex ( ) , privacy : . public ) to \( toUserNum . toHex ( ) , privacy : . public ) " )
2021-12-18 20:49:50 -08:00
success = true
2024-07-10 16:03:38 -05:00
2021-12-18 20:49:50 -08:00
} catch {
2024-06-28 08:50:49 -05:00
context . rollback ( )
2021-12-18 20:49:50 -08:00
let nsError = error as NSError
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Unresolved Core Data error in Send Message Function your database is corrupted running a node db reset should clean up the data. Error: \( nsError , privacy : . public ) " )
2021-12-18 20:49:50 -08:00
}
}
2021-12-15 23:53:45 -08:00
}
2021-12-18 20:49:50 -08:00
} catch {
2024-07-10 16:03:38 -05:00
2021-10-20 00:31:22 -07:00
}
}
return success
}
2024-07-10 16:03:38 -05:00
2023-01-14 09:42:09 -08:00
public func sendWaypoint ( waypoint : Waypoint ) -> Bool {
2023-01-21 07:28:50 -08:00
if waypoint . latitudeI = = 373346000 && waypoint . longitudeI = = - 1220090000 {
return false
}
2022-02-17 18:07:41 -08:00
var success = false
2023-01-14 09:42:09 -08:00
let fromNodeNum = UInt32 ( connectedPeripheral . num )
2022-08-12 08:58:10 -07:00
var meshPacket = MeshPacket ( )
2024-02-05 23:31:54 -07:00
meshPacket . to = Self . emptyNodeNum
2023-01-14 09:42:09 -08:00
meshPacket . from = fromNodeNum
2023-01-14 09:58:28 -08:00
meshPacket . wantAck = true
2022-08-12 08:58:10 -07:00
var dataMessage = DataMessage ( )
2023-10-20 16:14:29 -07:00
do {
dataMessage . payload = try waypoint . serializedData ( )
2024-05-29 16:40:07 -05:00
} catch {
2023-10-20 16:14:29 -07:00
// C o u l d n o t s e r i a l i a z e t h e p a y l o a d
return false
}
2024-07-10 16:03:38 -05:00
2022-11-13 09:25:00 -08:00
dataMessage . portnum = PortNum . waypointApp
2022-08-12 08:58:10 -07:00
meshPacket . decoded = dataMessage
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.waypoint.sent %@ " . localized , String ( fromNodeNum ) )
2023-01-01 14:48:50 -08:00
MeshLogger . log ( " 📍 \( logString ) " )
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-08-12 08:58:10 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
success = true
2024-07-10 16:03:38 -05:00
let wayPointEntity = queryCoreDataController . getWaypoint ( id : Int64 ( waypoint . id ) )
2023-01-16 23:16:57 -08:00
wayPointEntity . id = Int64 ( waypoint . id )
2023-01-29 08:28:44 -08:00
wayPointEntity . name = waypoint . name . count >= 1 ? waypoint . name : " Dropped Pin "
2023-01-16 17:40:28 -08:00
wayPointEntity . longDescription = waypoint . description_p
wayPointEntity . icon = Int64 ( waypoint . icon )
wayPointEntity . latitudeI = waypoint . latitudeI
wayPointEntity . longitudeI = waypoint . longitudeI
2023-02-05 20:23:31 -08:00
if waypoint . expire > 1 {
2023-02-03 19:20:23 -08:00
wayPointEntity . expire = Date . init ( timeIntervalSince1970 : Double ( waypoint . expire ) )
} else {
wayPointEntity . expire = nil
}
if waypoint . lockedTo > 0 {
wayPointEntity . locked = Int64 ( waypoint . lockedTo )
} else {
wayPointEntity . locked = 0
}
2023-02-05 20:23:31 -08:00
if wayPointEntity . created = = nil {
wayPointEntity . created = Date ( )
} else {
wayPointEntity . lastUpdated = Date ( )
}
2023-01-14 20:27:05 -08:00
do {
2024-07-10 16:03:38 -05:00
try context . save ( )
2024-06-23 16:11:02 -07:00
Logger . data . info ( " 💾 Updated Waypoint from Waypoint App Packet From: \( fromNodeNum . toHex ( ) , privacy : . public ) " )
2023-01-14 20:27:05 -08:00
} catch {
2024-07-10 16:03:38 -05:00
context . rollback ( )
2023-01-14 20:27:05 -08:00
let nsError = error as NSError
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Error Saving NodeInfoEntity from WAYPOINT_APP \( nsError , privacy : . public ) " )
2023-01-14 20:27:05 -08:00
}
2022-08-12 08:58:10 -07:00
}
2022-08-11 23:34:09 -07:00
return success
}
2024-07-10 16:03:38 -05:00
2024-04-30 12:44:47 -07:00
public func getPositionFromPhoneGPS ( destNum : Int64 ) -> Position ? {
2022-08-12 08:58:10 -07:00
var positionPacket = Position ( )
2024-05-14 22:39:07 -07:00
if #available ( iOS 17.0 , macOS 14.0 , * ) {
2024-07-10 16:03:38 -05:00
2024-05-26 10:37:22 -07:00
guard let lastLocation = LocationsHandler . shared . locationsArray . last else {
return nil
}
positionPacket . latitudeI = Int32 ( lastLocation . coordinate . latitude * 1e7 )
positionPacket . longitudeI = Int32 ( lastLocation . coordinate . longitude * 1e7 )
let timestamp = lastLocation . timestamp
positionPacket . time = UInt32 ( timestamp . timeIntervalSince1970 )
positionPacket . timestamp = UInt32 ( timestamp . timeIntervalSince1970 )
positionPacket . altitude = Int32 ( lastLocation . altitude )
positionPacket . satsInView = UInt32 ( LocationsHandler . satsInView )
2024-07-10 16:03:38 -05:00
2024-05-26 10:37:22 -07:00
let currentSpeed = lastLocation . speed
2024-05-29 16:40:07 -05:00
if currentSpeed > 0 && ( ! currentSpeed . isNaN || ! currentSpeed . isInfinite ) {
2024-05-26 10:37:22 -07:00
positionPacket . groundSpeed = UInt32 ( currentSpeed )
2023-12-06 12:32:17 -08:00
}
2024-05-26 10:37:22 -07:00
let currentHeading = lastLocation . course
if ( currentHeading > 0 && currentHeading <= 360 ) && ( ! currentHeading . isNaN || ! currentHeading . isInfinite ) {
positionPacket . groundTrack = UInt32 ( currentHeading )
}
2024-07-10 16:03:38 -05:00
2024-05-14 22:39:07 -07:00
} else {
2024-07-10 16:03:38 -05:00
2024-05-14 22:39:07 -07:00
positionPacket . latitudeI = Int32 ( LocationHelper . currentLocation . latitude * 1e7 )
positionPacket . longitudeI = Int32 ( LocationHelper . currentLocation . longitude * 1e7 )
let timestamp = LocationHelper . shared . locationManager . location ? . timestamp ? ? Date ( )
positionPacket . time = UInt32 ( timestamp . timeIntervalSince1970 )
positionPacket . timestamp = UInt32 ( timestamp . timeIntervalSince1970 )
positionPacket . altitude = Int32 ( LocationHelper . shared . locationManager . location ? . altitude ? ? 0 )
positionPacket . satsInView = UInt32 ( LocationHelper . satsInView )
let currentSpeed = LocationHelper . shared . locationManager . location ? . speed ? ? 0
2024-05-29 16:40:07 -05:00
if currentSpeed > 0 && ( ! currentSpeed . isNaN || ! currentSpeed . isInfinite ) {
2024-05-14 22:39:07 -07:00
positionPacket . groundSpeed = UInt32 ( currentSpeed )
}
let currentHeading = LocationHelper . shared . locationManager . location ? . course ? ? 0
if ( currentHeading > 0 && currentHeading <= 360 ) && ( ! currentHeading . isNaN || ! currentHeading . isInfinite ) {
positionPacket . groundTrack = UInt32 ( currentHeading )
}
2024-03-26 23:36:11 -07:00
}
return positionPacket
}
2024-07-10 16:03:38 -05:00
2024-03-26 23:36:11 -07:00
public func setFixedPosition ( fromUser : UserEntity , channel : Int32 ) -> Bool {
var adminPacket = AdminMessage ( )
2024-04-30 12:44:47 -07:00
guard let positionPacket = getPositionFromPhoneGPS ( destNum : fromUser . num ) else {
2024-03-26 23:36:11 -07:00
return false
}
adminPacket . setFixedPosition = positionPacket
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( fromUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
meshPacket . channel = UInt32 ( channel )
var dataMessage = DataMessage ( )
meshPacket . decoded = dataMessage
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2024-03-26 23:36:11 -07:00
let messageDescription = " 🚀 Sent Set Fixed Postion Admin Message to: \( fromUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-03-26 23:36:11 -07:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-03-26 23:36:11 -07:00
public func removeFixedPosition ( fromUser : UserEntity , channel : Int32 ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . removeFixedPosition = true
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( fromUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
meshPacket . channel = UInt32 ( channel )
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2024-03-26 23:36:11 -07:00
let messageDescription = " 🚀 Sent Remove Fixed Position Admin Message to: \( fromUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-03-26 23:36:11 -07:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-03-26 23:36:11 -07:00
public func sendPosition ( channel : Int32 , destNum : Int64 , wantResponse : Bool ) -> Bool {
var success = false
let fromNodeNum = connectedPeripheral . num
2024-04-30 12:44:47 -07:00
guard let positionPacket = getPositionFromPhoneGPS ( destNum : destNum ) else {
2024-02-27 16:23:54 -08:00
return false
2022-08-12 08:58:10 -07:00
}
2024-07-10 16:03:38 -05:00
2022-08-12 08:58:10 -07:00
var meshPacket = MeshPacket ( )
2024-01-13 09:35:38 -08:00
meshPacket . to = UInt32 ( destNum )
meshPacket . channel = UInt32 ( channel )
2023-02-05 18:36:35 -08:00
meshPacket . from = UInt32 ( fromNodeNum )
2022-08-12 08:58:10 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? positionPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . positionApp
dataMessage . wantResponse = wantResponse
meshPacket . decoded = dataMessage
} else {
return false
}
2024-07-10 16:03:38 -05:00
2022-08-12 08:58:10 -07:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-08-12 08:58:10 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
success = true
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.sharelocation %@ " . localized , String ( fromNodeNum ) )
2024-06-03 02:17:55 -07:00
Logger . services . debug ( " 📍 \( logString ) " )
2022-02-17 18:07:41 -08:00
}
return success
}
2022-02-22 09:08:06 -10:00
@objc func positionTimerFired ( timer : Timer ) {
// C h e c k f o r c o n n e c t e d n o d e
if connectedPeripheral != nil {
// S e n d a p o s i t i o n o u t t o t h e m e s h i f " s h a r e l o c a t i o n w i t h t h e m e s h " i s e n a b l e d i n s e t t i n g s
2023-04-26 09:19:45 -07:00
if UserDefaults . provideLocation {
2024-05-29 16:40:07 -05:00
_ = sendPosition ( channel : 0 , destNum : connectedPeripheral . num , wantResponse : false )
2022-02-22 09:08:06 -10:00
}
}
}
2024-07-10 16:03:38 -05:00
2023-02-02 22:03:27 -08:00
public func sendShutdown ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2022-05-27 19:18:33 -07:00
var adminPacket = AdminMessage ( )
2023-02-02 22:03:27 -08:00
adminPacket . shutdownSeconds = 5
2022-05-27 19:18:33 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2022-12-30 19:21:22 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
2022-05-29 22:02:25 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2023-02-02 22:03:27 -08:00
meshPacket . channel = UInt32 ( adminIndex )
2022-05-29 22:02:25 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2023-05-05 09:27:24 -07:00
let messageDescription = " 🚀 Sent Shutdown Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-12-30 19:21:22 -08:00
return true
2022-05-29 22:02:25 -07:00
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-02 22:03:27 -08:00
public func sendReboot ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2022-05-29 22:02:25 -07:00
var adminPacket = AdminMessage ( )
2023-02-02 22:03:27 -08:00
adminPacket . rebootSeconds = 5
2022-05-29 22:02:25 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-01-29 00:16:17 -08:00
meshPacket . to = UInt32 ( toUser . num )
2022-12-30 22:30:15 -08:00
meshPacket . from = UInt32 ( fromUser . num )
2022-06-27 08:30:49 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2023-02-02 22:03:27 -08:00
meshPacket . channel = UInt32 ( adminIndex )
2022-06-27 08:30:49 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2023-05-05 09:27:24 -07:00
let messageDescription = " 🚀 Sent Reboot Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-12-30 22:30:15 -08:00
return true
2022-06-27 08:30:49 -07:00
}
return false
}
2024-07-10 16:03:38 -05:00
2023-03-10 19:41:26 -08:00
public func sendRebootOta ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . rebootOtaSeconds = 5
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
meshPacket . channel = UInt32 ( adminIndex )
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2023-05-05 09:27:24 -07:00
let messageDescription = " 🚀 Sent Reboot OTA Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-03-10 19:41:26 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-01-14 20:26:45 -08:00
public func sendEnterDfuMode ( fromUser : UserEntity , toUser : UserEntity ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . enterDfuModeRequest = true
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-01-15 18:13:31 -08:00
meshPacket . channel = UInt32 ( 0 )
2024-01-14 20:26:45 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2024-01-15 18:13:31 -08:00
automaticallyReconnect = false
2024-01-14 20:26:45 -08:00
let messageDescription = " 🚀 Sent enter DFU mode Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-01-14 20:26:45 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2022-12-30 22:30:15 -08:00
public func sendFactoryReset ( fromUser : UserEntity , toUser : UserEntity ) -> Bool {
2022-06-27 08:30:49 -07:00
var adminPacket = AdminMessage ( )
2023-02-02 08:54:56 -08:00
adminPacket . factoryReset = 5
2022-06-27 08:30:49 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2022-12-30 22:30:15 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
2022-05-27 19:18:33 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-05-27 19:18:33 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🚀 Sent Factory Reset Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-10-09 07:38:19 -07:00
return true
2022-05-27 19:18:33 -07:00
}
2022-07-02 19:50:08 -07:00
return false
2022-05-27 19:18:33 -07:00
}
2024-07-10 16:03:38 -05:00
2022-12-30 22:30:15 -08:00
public func sendNodeDBReset ( fromUser : UserEntity , toUser : UserEntity ) -> Bool {
2022-10-02 09:19:03 -07:00
var adminPacket = AdminMessage ( )
2023-02-06 16:48:18 -08:00
adminPacket . nodedbReset = 5
2022-10-02 09:19:03 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2022-12-30 22:30:15 -08:00
meshPacket . to = UInt32 ( toUser . num )
2023-02-06 16:48:18 -08:00
meshPacket . from = 0 // U I n t 3 2 ( f r o m U s e r . n u m )
2022-10-02 09:19:03 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2022-10-02 09:19:03 -07:00
dataMessage . portnum = PortNum . adminApp
2024-07-10 16:03:38 -05:00
2022-10-02 09:19:03 -07:00
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🚀 Sent NodeDB Reset Admin Message to: \( toUser . longName ? ? " unknown " . localized ) from: \( fromUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-10-15 10:14:08 -07:00
return true
2022-10-02 09:19:03 -07:00
}
return false
}
2024-07-10 16:03:38 -05:00
2022-10-18 19:50:42 -07:00
public func connectToPreferredPeripheral ( ) -> Bool {
var success = false
// R e t u r n f a l s e i f w e a r e n o t p r o p e r l y c o n n e c t e d t o a d e v i c e , h a n d l e r e t r y l o g i c i n t h e v i e w f o r n o w
if connectedPeripheral = = nil || connectedPeripheral ! . peripheral . state != CBPeripheralState . connected {
self . disconnectPeripheral ( )
self . startScanning ( )
// T r y a n d c o n n e c t t o t h e p r e f e r r e d P e r i p h e r i a l f i r s t
let preferredPeripheral = peripherals . filter ( { $0 . peripheral . identifier . uuidString = = UserDefaults . standard . object ( forKey : " preferredPeripheralId " ) as ? String ? ? " " } ) . first
if preferredPeripheral != nil && preferredPeripheral ? . peripheral != nil {
connectTo ( peripheral : preferredPeripheral ! . peripheral )
success = true
}
} else if connectedPeripheral != nil && isSubscribed {
success = true
}
return success
}
2024-07-10 16:03:38 -05:00
2023-01-03 21:45:10 -08:00
public func getChannel ( channel : Channel , fromUser : UserEntity , toUser : UserEntity ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-01-03 21:45:10 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getChannelRequest = UInt32 ( channel . index + 1 )
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
2023-03-06 10:33:18 -08:00
meshPacket . from = UInt32 ( fromUser . num )
2023-01-03 21:45:10 -08:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-01-03 21:45:10 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🎛️ Requested Channel \( channel . index ) for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-03 21:45:10 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2022-12-21 11:47:02 -08:00
public func saveChannel ( channel : Channel , fromUser : UserEntity , toUser : UserEntity ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-12-21 11:47:02 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setChannel = channel
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
2023-03-06 10:33:18 -08:00
meshPacket . from = UInt32 ( fromUser . num )
2022-12-21 11:47:02 -08:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-12-21 11:47:02 -08:00
dataMessage . portnum = PortNum . adminApp
2023-01-03 21:45:10 -08:00
dataMessage . wantResponse = true
2022-12-21 11:47:02 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Channel \( channel . index ) for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-12-21 11:47:02 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2024-04-03 00:04:46 -07:00
public func saveChannelSet ( base64UrlString : String , addChannels : Bool = false ) -> Bool {
2022-10-18 19:50:42 -07:00
if isConnected {
2024-07-10 16:03:38 -05:00
2024-04-02 23:43:00 -07:00
var i : Int32 = 0
2024-05-05 08:38:27 -07:00
var myInfo : MyInfoEntity
2023-03-06 10:33:18 -08:00
// B e f o r e w e g e t s t a r t e d d e l e t e t h e e x i s t i n g c h a n n e l s f r o m t h e m y N o d e I n f o
2024-04-03 00:04:46 -07:00
if ! addChannels {
2024-04-02 21:49:36 -07:00
tryClearExistingChannels ( )
}
2024-07-10 16:03:38 -05:00
2022-10-28 09:02:37 -07:00
let decodedString = base64UrlString . base64urlToBase64 ( )
2022-10-18 19:50:42 -07:00
if let decodedData = Data ( base64Encoded : decodedString ) {
do {
2022-10-29 07:31:50 -07:00
let channelSet : ChannelSet = try ChannelSet ( serializedData : decodedData )
2022-10-19 16:58:49 -07:00
for cs in channelSet . settings {
2024-05-05 08:38:27 -07:00
if addChannels {
// W e a r e t r y i n g t o a d d a c h a n n e l s o l e t s g e t t h e l a s t i n d e x
2024-06-28 08:50:49 -05:00
let fetchMyInfoRequest = MyInfoEntity . fetchRequest ( )
2024-05-05 08:38:27 -07:00
fetchMyInfoRequest . predicate = NSPredicate ( format : " myNodeNum == %lld " , Int64 ( connectedPeripheral . num ) )
do {
2024-07-10 16:03:38 -05:00
let fetchedMyInfo = try context . fetch ( fetchMyInfoRequest )
2024-05-05 08:38:27 -07:00
if fetchedMyInfo . count = = 1 {
i = Int32 ( fetchedMyInfo [ 0 ] . channels ? . count ? ? - 1 )
myInfo = fetchedMyInfo [ 0 ]
// B a i l o u t i f t h e i n d e x i s n e g a t i v e o r b i g g e r t h a n o u r m a x o f 8
if i < 0 || i > 8 {
return false
}
// B a i l o u t i f t h e r e a r e n o c h a n n e l s o r i f t h e s a m e c h a n n e l n a m e a l r e a d y e x i s t s
guard let mutableChannels = myInfo . channels ! . mutableCopy ( ) as ? NSMutableOrderedSet else {
return false
}
if mutableChannels . first ( where : { ( $0 as AnyObject ) . name = = cs . name } ) is ChannelEntity {
return false
}
}
} catch {
2024-06-03 02:17:55 -07:00
Logger . data . error ( " Failed to find a node MyInfo to save these channels to: \( error . localizedDescription ) " )
2024-05-05 08:38:27 -07:00
}
}
2024-07-10 16:03:38 -05:00
2022-10-19 16:58:49 -07:00
var chan = Channel ( )
2024-04-02 23:43:00 -07:00
if i = = 0 {
2022-10-28 18:53:10 -07:00
chan . role = Channel . Role . primary
2023-03-06 10:33:18 -08:00
} else {
2022-10-28 18:53:10 -07:00
chan . role = Channel . Role . secondary
}
2022-10-29 07:31:50 -07:00
chan . settings = cs
2024-04-02 23:43:00 -07:00
chan . index = i
i += 1
2024-07-10 16:03:38 -05:00
2022-10-19 16:58:49 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setChannel = chan
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( connectedPeripheral . num )
2023-01-01 14:48:50 -08:00
meshPacket . from = UInt32 ( connectedPeripheral . num )
2022-10-19 16:58:49 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-10-29 07:31:50 -07:00
meshPacket . wantAck = true
meshPacket . channel = 0
2022-10-19 16:58:49 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2022-10-19 16:58:49 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-10-22 07:35:55 -07:00
self . connectedPeripheral . peripheral . writeValue ( binaryData , for : self . TORADIO_characteristic , type : . withResponse )
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.channel.sent %@ %d " . localized , String ( connectedPeripheral . num ) , chan . index )
2023-01-01 14:48:50 -08:00
MeshLogger . log ( " 🎛️ \( logString ) " )
2022-10-19 16:58:49 -07:00
}
}
// S a v e t h e L o R a C o n f i g a n d t h e d e v i c e w i l l r e b o o t
var adminPacket = AdminMessage ( )
adminPacket . setConfig . lora = channelSet . loraConfig
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( connectedPeripheral . num )
2023-03-06 10:33:18 -08:00
meshPacket . from = UInt32 ( connectedPeripheral . num )
2022-10-19 16:58:49 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-10-28 18:53:10 -07:00
meshPacket . wantAck = true
2022-10-29 07:44:43 -07:00
meshPacket . channel = 0
2022-10-19 16:58:49 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2022-10-19 16:58:49 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-10-28 09:02:37 -07:00
self . connectedPeripheral . peripheral . writeValue ( binaryData , for : self . TORADIO_characteristic , type : . withResponse )
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.lora.config.sent %@ " . localized , String ( connectedPeripheral . num ) )
2023-03-28 14:52:11 -07:00
MeshLogger . log ( " 📻 \( logString ) " )
2022-10-19 16:58:49 -07:00
}
2024-07-10 16:03:38 -05:00
2024-04-03 08:13:16 -07:00
if self . connectedPeripheral != nil {
self . sendWantConfig ( )
return true
}
2024-07-10 16:03:38 -05:00
2022-10-18 19:50:42 -07:00
} catch {
2022-10-19 16:58:49 -07:00
return false
2022-10-18 19:50:42 -07:00
}
}
}
return false
}
2024-07-10 16:03:38 -05:00
2023-01-19 22:04:18 -08:00
public func saveUser ( config : User , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2022-06-12 01:25:42 -07:00
var adminPacket = AdminMessage ( )
2022-07-02 19:50:08 -07:00
adminPacket . setOwner = config
2022-06-18 00:08:01 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-01-19 22:04:18 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-06-18 00:08:01 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-06-18 00:08:01 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return 0
}
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved User Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-18 00:08:01 -07:00
}
2022-07-11 15:43:25 -07:00
return 0
2022-06-18 00:08:01 -07:00
}
2024-07-10 16:03:38 -05:00
2023-12-21 12:59:08 -08:00
public func removeNode ( node : NodeInfoEntity , connectedNodeNum : Int64 ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . removeByNodenum = UInt32 ( node . num )
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( connectedNodeNum )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
if let serializedData : Data = try ? adminPacket . serializedData ( ) {
dataMessage . payload = serializedData
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
} else {
return false
}
2023-12-21 12:59:08 -08:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-07-10 16:03:38 -05:00
2024-05-29 16:40:07 -05:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2023-12-21 12:59:08 -08:00
do {
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2024-07-10 16:03:38 -05:00
context . delete ( node . user ! )
context . delete ( node )
try context . save ( )
2023-12-21 12:59:08 -08:00
return true
} catch {
2024-07-10 16:03:38 -05:00
context . rollback ( )
2023-12-21 12:59:08 -08:00
let nsError = error as NSError
2024-06-29 11:05:29 -07:00
Logger . data . error ( " 🚫 Error deleting node from core data: \( nsError ) " )
2023-12-21 12:59:08 -08:00
}
}
return false
}
2024-07-10 16:03:38 -05:00
2024-03-29 14:37:09 -07:00
public func setFavoriteNode ( node : NodeInfoEntity , connectedNodeNum : Int64 ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . setFavoriteNode = UInt32 ( node . num )
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( connectedNodeNum )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2024-03-29 14:37:09 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-07-10 16:03:38 -05:00
2024-05-29 16:40:07 -05:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2024-03-29 14:37:09 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2024-04-13 09:46:13 -07:00
return true
2024-03-29 14:37:09 -07:00
}
return false
}
2024-07-10 16:03:38 -05:00
2024-03-29 14:37:09 -07:00
public func removeFavoriteNode ( node : NodeInfoEntity , connectedNodeNum : Int64 ) -> Bool {
var adminPacket = AdminMessage ( )
adminPacket . removeFavoriteNode = UInt32 ( node . num )
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( connectedNodeNum )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2024-03-29 14:37:09 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-07-10 16:03:38 -05:00
2024-05-29 16:40:07 -05:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2024-03-29 14:37:09 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2024-04-13 09:46:13 -07:00
return true
2024-03-29 14:37:09 -07:00
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-09 22:59:39 -08:00
public func saveLicensedUser ( ham : HamParameters , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
var adminPacket = AdminMessage ( )
adminPacket . setHamMode = ham
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-09 22:59:39 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Ham Parameters for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-02-09 22:59:39 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2023-02-03 07:29:12 -08:00
public func saveBluetoothConfig ( config : Config . BluetoothConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2022-08-20 12:31:52 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . bluetooth = config
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-03 07:29:12 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-08-20 12:31:52 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2022-06-18 00:08:01 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-06-18 00:08:01 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Bluetooth Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertBluetoothConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-18 00:08:01 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-11 15:43:25 -07:00
return 0
2022-06-18 00:08:01 -07:00
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveDeviceConfig ( config : Config . DeviceConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-06-21 02:43:37 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . device = config
2024-07-10 16:03:38 -05:00
2022-06-21 02:43:37 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-03 07:29:12 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-06-21 02:43:37 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-06-21 02:43:37 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-06-21 02:43:37 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Device Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertDeviceConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-21 02:43:37 -07:00
}
2022-07-11 15:43:25 -07:00
return 0
2022-06-21 02:43:37 -07:00
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveDisplayConfig ( config : Config . DisplayConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2022-06-21 10:02:05 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . display = config
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-03 07:29:12 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
if adminIndex > 0 {
meshPacket . channel = UInt32 ( adminIndex )
}
2022-06-21 10:02:05 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-06-21 10:02:05 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-06-21 10:02:05 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Display Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertDisplayConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-21 10:02:05 -07:00
}
2022-07-11 15:43:25 -07:00
return 0
2022-06-21 10:02:05 -07:00
}
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
public func saveLoRaConfig ( config : Config . LoRaConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-06-18 00:08:01 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . lora = config
2022-06-12 01:25:42 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-01-20 19:14:49 -08:00
meshPacket . to = UInt32 ( toUser . num )
2023-03-14 19:16:04 -07:00
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-06-12 01:25:42 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-06-12 01:25:42 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-06-12 01:25:42 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved LoRa Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertLoRaConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-12 01:25:42 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-11 15:43:25 -07:00
return 0
2022-06-11 09:50:25 -07:00
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func savePositionConfig ( config : Config . PositionConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-06-21 10:15:47 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . position = config
2024-07-10 16:03:38 -05:00
2022-06-21 10:15:47 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-03 07:29:12 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-06-21 10:15:47 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-06-21 10:15:47 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-06-21 10:15:47 -07:00
dataMessage . portnum = PortNum . adminApp
2024-07-10 16:03:38 -05:00
2022-06-21 10:15:47 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Position Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertPositionConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-06-21 10:15:47 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-11 15:43:25 -07:00
return 0
2022-06-21 10:15:47 -07:00
}
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
public func savePowerConfig ( config : Config . PowerConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setConfig . power = config
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2024-02-19 21:30:19 -07:00
dataMessage . portnum = PortNum . adminApp
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
let messageDescription = " 🛟 Saved Power Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertPowerConfigPacket ( config : config , nodeNum : toUser . num )
2024-02-19 21:30:19 -07:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveNetworkConfig ( config : Config . NetworkConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-08-02 09:44:59 -07:00
var adminPacket = AdminMessage ( )
2022-09-07 22:33:44 -07:00
adminPacket . setConfig . network = config
2024-07-10 16:03:38 -05:00
2022-08-02 09:44:59 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-03 07:29:12 -08:00
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-08-02 09:44:59 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-08-02 09:44:59 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-08-02 09:44:59 -07:00
dataMessage . portnum = PortNum . adminApp
2024-07-10 16:03:38 -05:00
2022-08-02 09:44:59 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Network Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertNetworkConfigPacket ( config : config , nodeNum : toUser . num )
2022-08-02 09:44:59 -07:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2022-08-02 09:44:59 -07:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
public func saveAmbientLightingModuleConfig ( config : ModuleConfig . AmbientLightingConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . ambientLighting = config
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-11-28 20:03:08 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
let messageDescription = " 🛟 Saved Ambient Lighting Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertAmbientLightingModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-11-28 20:03:08 -08:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveCannedMessageModuleConfig ( config : ModuleConfig . CannedMessageConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-07-02 12:18:20 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . cannedMessage = config
2024-07-10 16:03:38 -05:00
2022-07-02 12:18:20 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
2023-02-03 07:29:12 -08:00
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-07-02 12:18:20 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-07-02 12:18:20 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-07-02 12:18:20 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Canned Message Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertCannedMessagesModuleConfigPacket ( config : config , nodeNum : toUser . num )
2022-07-11 15:43:25 -07:00
return Int64 ( meshPacket . id )
2022-07-02 12:34:45 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-11 15:43:25 -07:00
return 0
2022-07-02 12:34:45 -07:00
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveCannedMessageModuleMessages ( messages : String , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2022-07-08 12:05:39 -07:00
var adminPacket = AdminMessage ( )
2022-08-15 19:40:46 -07:00
adminPacket . setCannedMessageModuleMessages = messages
2024-07-10 16:03:38 -05:00
2022-07-08 12:05:39 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
2023-02-03 07:29:12 -08:00
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
2022-07-08 12:05:39 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-12 08:58:10 -07:00
meshPacket . wantAck = true
2022-07-08 12:05:39 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2022-07-08 12:05:39 -07:00
dataMessage . portnum = PortNum . adminApp
2023-02-03 07:29:12 -08:00
dataMessage . wantResponse = true
2022-07-08 12:05:39 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-05-05 09:27:24 -07:00
let messageDescription = " 🛟 Saved Canned Message Module Messages for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
2022-07-09 06:42:30 -07:00
return Int64 ( meshPacket . id )
2022-07-08 12:05:39 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-09 06:42:30 -07:00
return 0
2022-07-08 12:05:39 -07:00
}
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
public func saveDetectionSensorModuleConfig ( config : ModuleConfig . DetectionSensorConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . detectionSensor = config
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-08-26 20:45:15 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved Detection Sensor Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertDetectionSensorModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-08-26 20:45:15 -07:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveExternalNotificationModuleConfig ( config : ModuleConfig . ExternalNotificationConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . externalNotification = config
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-03 07:29:12 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved External Notification Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertExternalNotificationModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-02-03 07:29:12 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
public func savePaxcounterModuleConfig ( config : ModuleConfig . PaxcounterConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . paxcounter = config
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2024-02-25 11:24:01 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
let messageDescription = " 🛟 Saved PAX Counter Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertPaxCounterModuleConfigPacket ( config : config , nodeNum : toUser . num )
2024-02-25 11:24:01 -08:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-03-25 22:14:39 -07:00
public func saveRtttlConfig ( ringtone : String , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
var adminPacket = AdminMessage ( )
2023-03-25 22:14:39 -07:00
adminPacket . setRingtoneMessage = ringtone
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-03-25 14:30:18 -07:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved RTTTL Ringtone Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertRtttlConfigPacket ( ringtone : ringtone , nodeNum : toUser . num )
2023-03-25 14:30:18 -07:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveMQTTConfig ( config : ModuleConfig . MQTTConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . mqtt = config
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-03 07:29:12 -08:00
dataMessage . portnum = PortNum . adminApp
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved MQTT Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertMqttModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-02-03 07:29:12 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveRangeTestModuleConfig ( config : ModuleConfig . RangeTestConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . rangeTest = config
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-03 07:29:12 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved Range Test Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertRangeTestModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-02-03 07:29:12 -08:00
return Int64 ( meshPacket . id )
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
return 0
}
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
public func saveSerialModuleConfig ( config : ModuleConfig . SerialConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var adminPacket = AdminMessage ( )
adminPacket . setModuleConfig . serial = config
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-03 07:29:12 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved Serial Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertSerialModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-02-03 07:29:12 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
public func saveStoreForwardModuleConfig ( config : ModuleConfig . StoreForwardConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var adminPacket = AdminMessage ( )
2023-08-26 20:45:15 -07:00
adminPacket . setModuleConfig . storeForward = config
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-03 07:29:12 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-02-03 07:29:12 -08:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
let messageDescription = " 🛟 Saved Store & Forward Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertStoreForwardModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-02-03 07:29:12 -08:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2023-08-26 20:45:15 -07:00
public func saveTelemetryModuleConfig ( config : ModuleConfig . TelemetryConfig , fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Int64 {
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var adminPacket = AdminMessage ( )
2023-08-26 20:45:15 -07:00
adminPacket . setModuleConfig . telemetry = config
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return 0
}
dataMessage . payload = adminData
2023-08-17 16:30:48 -05:00
dataMessage . portnum = PortNum . adminApp
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
let messageDescription = " Saved Telemetry Module Config for \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
updateCoreDataController . upsertTelemetryModuleConfigPacket ( config : config , nodeNum : toUser . num )
2023-08-17 16:30:48 -05:00
return Int64 ( meshPacket . id )
}
return 0
}
2024-07-10 16:03:38 -05:00
2022-10-09 18:32:21 -07:00
public func getChannel ( channelIndex : UInt32 , fromUser : UserEntity , toUser : UserEntity , wantResponse : Bool ) -> Bool {
2024-07-10 16:03:38 -05:00
2022-07-31 19:05:47 -04:00
var adminPacket = AdminMessage ( )
adminPacket . getChannelRequest = channelIndex
2024-07-10 16:03:38 -05:00
2022-07-31 19:05:47 -04:00
var meshPacket : MeshPacket = MeshPacket ( )
2022-10-09 18:32:21 -07:00
meshPacket . to = UInt32 ( toUser . num )
2023-02-02 23:17:23 -08:00
meshPacket . from = UInt32 ( fromUser . num )
2022-07-31 19:05:47 -04:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = wantResponse
2024-07-10 16:03:38 -05:00
2022-07-31 19:05:47 -04:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2022-07-31 19:05:47 -04:00
dataMessage . portnum = PortNum . adminApp
2022-07-31 19:53:44 -04:00
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2022-07-31 19:05:47 -04:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Sent a Get Channel \( channelIndex ) Request Admin Message for node: \( toUser . longName ? ? " unknown " . localized ) ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
2022-10-09 18:32:21 -07:00
return true
2022-07-31 19:05:47 -04:00
}
2024-07-10 16:03:38 -05:00
2022-07-31 19:05:47 -04:00
return false
}
2024-07-10 16:03:38 -05:00
2023-03-06 10:33:18 -08:00
public func getCannedMessageModuleMessages ( destNum : Int64 , wantResponse : Bool ) -> Bool {
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
var adminPacket = AdminMessage ( )
2022-08-15 19:40:46 -07:00
adminPacket . getCannedMessageModuleMessagesRequest = true
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
2023-02-02 23:17:23 -08:00
meshPacket . to = UInt32 ( destNum )
meshPacket . from = UInt32 ( connectedPeripheral . num )
2022-07-26 07:35:16 -07:00
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
2022-08-11 23:34:09 -07:00
meshPacket . wantAck = true
2022-08-02 09:44:59 -07:00
meshPacket . decoded . wantResponse = wantResponse
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2022-07-26 07:35:16 -07:00
dataMessage . portnum = PortNum . adminApp
2022-08-03 07:28:11 -07:00
dataMessage . wantResponse = wantResponse
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-07-10 16:03:38 -05:00
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-07-10 16:03:38 -05:00
2023-08-09 23:36:00 -07:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2022-10-15 10:14:08 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2023-05-05 09:27:24 -07:00
let logString = String . localizedStringWithFormat ( " mesh.log.cannedmessages.messages.get %@ " . localized , String ( connectedPeripheral . num ) )
2023-01-01 14:48:50 -08:00
MeshLogger . log ( " 🥫 \( logString ) " )
2022-10-15 10:14:08 -07:00
return true
2022-07-26 07:35:16 -07:00
}
2024-07-10 16:03:38 -05:00
2022-07-26 07:35:16 -07:00
return false
}
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
public func requestBluetoothConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . bluetoothConfig
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-23 17:56:04 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
let messageDescription = " 🛎️ Requested Bluetooth Config on admin channel \( adminIndex ) for node: \( String ( connectedPeripheral . num ) ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-23 17:56:04 -08:00
return true
}
2023-01-31 22:08:03 -08:00
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
public func requestDeviceConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . deviceConfig
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 22:08:03 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Device Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 22:08:03 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
public func requestDisplayConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . displayConfig
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 22:08:03 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Display Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 22:08:03 -08:00
return true
}
2023-01-23 17:56:04 -08:00
return false
}
2024-07-10 16:03:38 -05:00
2023-01-23 17:56:04 -08:00
public func requestLoRaConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . loraConfig
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-20 19:14:49 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested LoRa Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
return true
}
2024-07-10 16:03:38 -05:00
2023-01-20 19:14:49 -08:00
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
public func requestNetworkConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . networkConfig
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 22:08:03 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Network Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-07-10 16:03:38 -05:00
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 22:08:03 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
public func requestPositionConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . positionConfig
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 22:08:03 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-31 22:08:03 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Position Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-11-28 20:03:08 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
public func requestPowerConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
var adminPacket = AdminMessage ( )
adminPacket . getConfigRequest = AdminMessage . ConfigType . powerConfig
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2024-02-19 21:30:19 -07:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-02-19 21:30:19 -07:00
let messageDescription = " 🛎️ Requested Power Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-02-19 21:30:19 -07:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
public func requestAmbientLightingConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . ambientlightingConfig
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-11-28 20:03:08 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-11-28 20:03:08 -08:00
let messageDescription = " 🛎️ Requested Ambient Lighting Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 22:08:03 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
public func requestCannedMessagesModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . cannedmsgConfig
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-02-01 09:19:45 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Canned Messages Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-02-01 09:19:45 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
public func requestExternalNotificationModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . extnotifConfig
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-02-01 09:19:45 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested External Notificaiton Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-02-01 09:19:45 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
public func requestPaxCounterModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . paxcounterConfig
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2024-02-25 11:24:01 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-02-25 11:24:01 -08:00
let messageDescription = " 🛎️ Requested PAX Counter Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-02-25 11:24:01 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
public func requestRtttlConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
var adminPacket = AdminMessage ( )
adminPacket . getRingtoneRequest = true
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-03-25 14:30:18 -07:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-03-25 14:30:18 -07:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested RTTTL Ringtone Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-03-25 14:30:18 -07:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
public func requestRangeTestModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . rangetestConfig
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 23:52:19 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Range Test Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 23:52:19 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
public func requestMqttModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . mqttConfig
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-02-01 09:19:45 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
let messageDescription = " 🛎️ Requested MQTT Module Config on admin channel \( adminIndex ) for node: \( String ( connectedPeripheral . num ) ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-02-01 09:19:45 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
public func requestDetectionSensorModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . detectionsensorConfig
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-08-17 16:30:48 -05:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-08-17 16:30:48 -05:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Detection Sensor Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-08-17 16:30:48 -05:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
public func requestSerialModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . serialConfig
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-02-01 09:19:45 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-02-01 09:19:45 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Serial Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2024-01-14 21:00:54 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
public func requestStoreAndForwardModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . storeforwardConfig
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2024-01-14 21:00:54 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-01-14 21:00:54 -08:00
let messageDescription = " 🛎️ Requested Store and Forward Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-02-01 09:19:45 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
public func requestTelemetryModuleConfig ( fromUser : UserEntity , toUser : UserEntity , adminIndex : Int32 ) -> Bool {
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var adminPacket = AdminMessage ( )
adminPacket . getModuleConfigRequest = AdminMessage . ModuleConfigType . telemetryConfig
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . channel = UInt32 ( adminIndex )
2023-02-02 23:17:23 -08:00
meshPacket . wantAck = true
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let adminData : Data = try ? adminPacket . serializedData ( ) else {
return false
}
dataMessage . payload = adminData
2023-01-31 23:52:19 -08:00
dataMessage . portnum = PortNum . adminApp
dataMessage . wantResponse = true
2024-07-10 16:03:38 -05:00
2023-01-31 23:52:19 -08:00
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2023-10-21 13:48:59 -07:00
let messageDescription = " 🛎️ Requested Telemetry Module Config on admin channel \( adminIndex ) for node: \( toUser . longName ? ? " unknown " . localized ) "
2024-06-23 12:25:08 -07:00
if sendAdminMessageToRadio ( meshPacket : meshPacket , adminDescription : messageDescription ) {
2023-01-31 23:52:19 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2022-07-08 12:05:39 -07:00
// S e n d a n a d m i n m e s s a g e t o a r a d i o , s a v e a m e s s a g e t o c o r e d a t a f o r l o g g i n g
2024-06-23 12:25:08 -07:00
private func sendAdminMessageToRadio ( meshPacket : MeshPacket , adminDescription : String ) -> Bool {
2024-07-10 16:03:38 -05:00
2022-07-09 06:42:30 -07:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-07-10 16:03:38 -05:00
2024-05-29 16:40:07 -05:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
2024-06-23 12:25:08 -07:00
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
Logger . mesh . debug ( " \( adminDescription ) " )
return true
2022-07-08 12:05:39 -07:00
}
2022-07-09 06:42:30 -07:00
return false
2022-07-08 12:05:39 -07:00
}
2024-07-10 16:03:38 -05:00
2024-02-10 17:21:31 -08:00
public func requestStoreAndForwardClientHistory ( fromUser : UserEntity , toUser : UserEntity ) -> Bool {
2024-07-10 16:03:38 -05:00
2024-02-10 17:21:31 -08:00
// / s e n d a r e q u e s t f o r C l i e n t H i s t o r y w i t h a t i m e p e r i o d m a t c h i n g t h e h e a r t b e a t
var sfPacket = StoreAndForward ( )
sfPacket . rr = StoreAndForward . RequestResponse . clientHistory
2024-02-11 17:45:03 -08:00
sfPacket . history . window = UInt32 ( toUser . userNode ? . storeForwardConfig ? . historyReturnWindow ? ? 120 )
2024-02-12 16:35:29 -08:00
sfPacket . history . lastRequest = UInt32 ( toUser . userNode ? . storeForwardConfig ? . lastRequest ? ? 0 )
2024-02-10 17:21:31 -08:00
var meshPacket : MeshPacket = MeshPacket ( )
meshPacket . to = UInt32 ( toUser . num )
meshPacket . from = UInt32 ( fromUser . num )
meshPacket . id = UInt32 . random ( in : UInt32 ( UInt8 . max ) . . < UInt32 . max )
meshPacket . priority = MeshPacket . Priority . reliable
meshPacket . wantAck = true
var dataMessage = DataMessage ( )
2024-06-02 18:32:14 -07:00
guard let sfData : Data = try ? sfPacket . serializedData ( ) else {
return false
}
dataMessage . payload = sfData
2024-02-10 17:21:31 -08:00
dataMessage . portnum = PortNum . storeForwardApp
dataMessage . wantResponse = true
meshPacket . decoded = dataMessage
2024-07-10 16:03:38 -05:00
2024-02-10 17:21:31 -08:00
var toRadio : ToRadio !
toRadio = ToRadio ( )
toRadio . packet = meshPacket
2024-06-02 18:32:14 -07:00
guard let binaryData : Data = try ? toRadio . serializedData ( ) else {
return false
}
2024-02-10 17:21:31 -08:00
if connectedPeripheral ? . peripheral . state ? ? CBPeripheralState . disconnected = = CBPeripheralState . connected {
connectedPeripheral . peripheral . writeValue ( binaryData , for : TORADIO_characteristic , type : . withResponse )
2024-06-23 16:11:02 -07:00
Logger . mesh . debug ( " 📮 Sent a request for a Store & Forward Client History to \( toUser . num . toHex ( ) , privacy : . public ) for the last \( 120 , privacy : . public ) minutes. " )
2024-02-10 17:21:31 -08:00
return true
}
return false
}
2024-07-10 16:03:38 -05:00
2023-10-01 12:25:38 -07:00
func storeAndForwardPacket ( packet : MeshPacket , connectedNodeNum : Int64 , context : NSManagedObjectContext ) {
if let storeAndForwardMessage = try ? StoreAndForward ( serializedData : packet . decoded . payload ) {
2024-02-11 17:45:03 -08:00
// H a n d l e e a c h o f t h e s t o r e a n d f o r w a r d r e q u e s t / r e s p o n s e m e s s a g e s
2023-10-01 12:25:38 -07:00
switch storeAndForwardMessage . rr {
case . unset :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📮 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerError :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " ☠️ Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerHeartbeat :
// / W h e n w e g e t a r o u t e r h e a r t b e a t w e k n o w t h e r e i s a s t o r e a n d f o r w a r d n o d e o n t h e n e t w o r k
2024-02-10 17:21:31 -08:00
// / C h e c k i f i t i s t h e p r i m a r y S & F R o u t e r a n d s a v e t h e t i m e s t a m p o f t h e l a s t h e a r t b e a t s o t h a t w e c a n s h o w t h e r e q u e s t m e s s a g e h i s t o r y m e n u i t e m o n n o d e l o n g p r e s s i f t h e r o u t e r h a s b e e n s e e n r e c e n t l y
2024-05-29 16:40:07 -05:00
if storeAndForwardMessage . heartbeat . secondary = = 0 {
2024-07-10 16:03:38 -05:00
guard let routerNode = queryCoreDataController . getNodeInfo ( id : Int64 ( packet . from ) ) else {
2024-02-10 17:21:31 -08:00
return
}
if routerNode . storeForwardConfig != nil {
routerNode . storeForwardConfig ? . enabled = true
routerNode . storeForwardConfig ? . isRouter = storeAndForwardMessage . heartbeat . secondary = = 0
routerNode . storeForwardConfig ? . lastHeartbeat = Date ( )
} else {
let newConfig = StoreForwardConfigEntity ( context : context )
newConfig . enabled = true
newConfig . isRouter = storeAndForwardMessage . heartbeat . secondary = = 0
newConfig . lastHeartbeat = Date ( )
2024-02-11 17:45:03 -08:00
routerNode . storeForwardConfig = newConfig
2024-02-10 17:21:31 -08:00
}
2024-07-10 16:03:38 -05:00
2024-02-10 17:21:31 -08:00
do {
try context . save ( )
} catch {
context . rollback ( )
2024-06-03 02:17:55 -07:00
Logger . data . error ( " Save Store and Forward Router Error " )
2023-10-01 12:25:38 -07:00
}
}
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 💓 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerPing :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🏓 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerPong :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🏓 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerBusy :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🐝 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerHistory :
2024-02-11 17:45:03 -08:00
// / S e t t h e R o u t e r H i s t o r y L a s t R e q u e s t V a l u e
2024-07-10 16:03:38 -05:00
guard let routerNode = queryCoreDataController . getNodeInfo ( id : Int64 ( packet . from ) ) else {
2024-02-11 17:45:03 -08:00
return
}
if routerNode . storeForwardConfig != nil {
2024-02-12 16:35:29 -08:00
routerNode . storeForwardConfig ? . lastRequest = Int32 ( storeAndForwardMessage . history . lastRequest )
2024-02-11 17:45:03 -08:00
} else {
let newConfig = StoreForwardConfigEntity ( context : context )
2024-02-12 16:35:29 -08:00
newConfig . lastRequest = Int32 ( storeAndForwardMessage . history . lastRequest )
2024-02-11 17:45:03 -08:00
routerNode . storeForwardConfig = newConfig
}
2024-07-10 16:03:38 -05:00
2024-02-11 17:45:03 -08:00
do {
try context . save ( )
} catch {
context . rollback ( )
2024-06-03 02:17:55 -07:00
Logger . data . error ( " Save Store and Forward Router Error " )
2024-02-11 17:45:03 -08:00
}
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📜 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . routerStats :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📊 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientError :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " ☠️ Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientHistory :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📜 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientStats :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📊 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientPing :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🏓 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientPong :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🏓 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . clientAbort :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 🛑 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2023-10-01 12:25:38 -07:00
case . UNRECOGNIZED :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 📮 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2024-02-12 16:35:29 -08:00
case . routerTextDirect :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " 💬 Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2024-07-10 16:03:38 -05:00
updateCoreDataController . textMessageAppPacket ( packet : packet , wantRangeTestPackets : false , connectedNode : connectedNodeNum , storeForward : true )
2024-02-12 16:35:29 -08:00
case . routerTextBroadcast :
2024-06-23 16:11:02 -07:00
MeshLogger . log ( " ✉️ Store and Forward \( storeAndForwardMessage . rr ) message received from \( packet . from . toHex ( ) ) " )
2024-07-10 16:03:38 -05:00
updateCoreDataController . textMessageAppPacket ( packet : packet , wantRangeTestPackets : false , connectedNode : connectedNodeNum , storeForward : true )
2023-10-01 12:25:38 -07:00
}
}
}
2024-07-10 16:03:38 -05:00
2023-03-09 14:23:15 -06:00
public func tryClearExistingChannels ( ) {
2023-03-14 12:44:10 -07:00
// B e f o r e w e g e t s t a r t e d d e l e t e t h e e x i s t i n g c h a n n e l s f r o m t h e m y N o d e I n f o
2024-06-28 08:50:49 -05:00
let fetchMyInfoRequest = MyInfoEntity . fetchRequest ( )
2023-03-09 14:23:15 -06:00
fetchMyInfoRequest . predicate = NSPredicate ( format : " myNodeNum == %lld " , Int64 ( connectedPeripheral . num ) )
2024-07-10 16:03:38 -05:00
2023-03-09 14:23:15 -06:00
do {
2024-06-28 08:50:49 -05:00
let fetchedMyInfo = try context . fetch ( fetchMyInfoRequest )
2023-03-09 14:23:15 -06:00
if fetchedMyInfo . count = = 1 {
2023-03-14 13:01:35 -07:00
let mutableChannels = fetchedMyInfo [ 0 ] . channels ? . mutableCopy ( ) as ? NSMutableOrderedSet
mutableChannels ? . removeAllObjects ( )
2023-03-09 14:23:15 -06:00
fetchedMyInfo [ 0 ] . channels = mutableChannels
do {
2024-06-28 08:50:49 -05:00
try context . save ( )
2023-03-09 14:23:15 -06:00
} catch {
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Failed to clear existing channels from local app database: \( error . localizedDescription , privacy : . public ) " )
2023-03-09 14:23:15 -06:00
}
}
} catch {
2024-06-23 16:11:02 -07:00
Logger . data . error ( " Failed to find a node MyInfo to save these channels to: \( error . localizedDescription , privacy : . public ) " )
2023-03-09 14:23:15 -06:00
}
}
2021-09-10 07:41:26 -07:00
}
2022-12-04 00:28:26 -08:00
// MARK: - C B C e n t r a l M a n a g e r i m p l m e n t a t i o n
extension BLEManager : CBCentralManagerDelegate {
2024-07-10 16:03:38 -05:00
2022-12-04 00:28:26 -08:00
// MARK: B l u e t o o t h e n a b l e d / d i s a b l e d
func centralManagerDidUpdateState ( _ central : CBCentralManager ) {
if central . state = = CBManagerState . poweredOn {
2024-06-24 06:31:45 -07:00
Logger . services . info ( " ✅ [BLE] powered on " )
2022-12-04 00:28:26 -08:00
isSwitchedOn = true
startScanning ( )
2023-03-06 10:33:18 -08:00
} else {
2022-12-04 00:28:26 -08:00
isSwitchedOn = false
}
2024-07-10 16:03:38 -05:00
2022-12-04 00:28:26 -08:00
var status = " "
2024-07-10 16:03:38 -05:00
2022-12-04 00:28:26 -08:00
switch central . state {
2023-03-06 13:26:04 -08:00
case . poweredOff :
status = " BLE is powered off "
case . poweredOn :
status = " BLE is poweredOn "
case . resetting :
status = " BLE is resetting "
case . unauthorized :
status = " BLE is unauthorized "
case . unknown :
status = " BLE is unknown "
case . unsupported :
status = " BLE is unsupported "
default :
status = " default "
2022-12-04 00:28:26 -08:00
}
2024-06-24 06:31:45 -07:00
Logger . services . info ( " 📜 [BLE] Bluetooth status: \( status ) " )
2022-12-04 00:28:26 -08:00
}
2024-07-10 16:03:38 -05:00
2022-12-04 00:28:26 -08:00
// C a l l e d e a c h t i m e a p e r i p h e r a l i s d i s c o v e r e d
func centralManager ( _ central : CBCentralManager , didDiscover peripheral : CBPeripheral , advertisementData : [ String : Any ] , rssi RSSI : NSNumber ) {
2024-07-10 16:03:38 -05:00
2023-05-04 20:11:42 -07:00
if self . automaticallyReconnect && peripheral . identifier . uuidString = = UserDefaults . standard . object ( forKey : " preferredPeripheralId " ) as ? String ? ? " " {
2022-12-07 16:50:24 -08:00
self . connectTo ( peripheral : peripheral )
2024-06-23 16:11:02 -07:00
Logger . services . info ( " ✅ [BLE] Reconnecting to prefered peripheral: \( peripheral . name ? ? " Unknown " , privacy : . public ) " )
2022-12-07 16:50:24 -08:00
}
2022-12-04 00:28:26 -08:00
let name = advertisementData [ CBAdvertisementDataLocalNameKey ] as ? String
2023-09-02 17:37:35 -07:00
let device = Peripheral ( id : peripheral . identifier . uuidString , num : 0 , name : name ? ? " Unknown " , shortName : " ? " , longName : name ? ? " Unknown " , firmwareVersion : " Unknown " , rssi : RSSI . intValue , lastUpdate : Date ( ) , peripheral : peripheral )
2022-12-04 00:28:26 -08:00
let index = peripherals . map { $0 . peripheral } . firstIndex ( of : peripheral )
2024-07-10 16:03:38 -05:00
2022-12-04 00:28:26 -08:00
if let peripheralIndex = index {
peripherals [ peripheralIndex ] = device
} else {
peripherals . append ( device )
}
let today = Date ( )
let visibleDuration = Calendar . current . date ( byAdding : . second , value : - 5 , to : today ) !
self . peripherals . removeAll ( where : { $0 . lastUpdate < visibleDuration } )
}
}