mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Refactor Packet Handlers out out BLE Manger for testing and potentially TCP connections on iOS and serial on macOS
This commit is contained in:
parent
bd5623758f
commit
9057f77e48
20 changed files with 902 additions and 2754 deletions
|
|
@ -37,10 +37,10 @@
|
|||
DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860D26F69BAE00DC5189 /* NodeMap.swift */; };
|
||||
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; };
|
||||
DD9D8F2F2764403B00080993 /* Meshtastic.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DD9D8F2D2764403B00080993 /* Meshtastic.xcdatamodeld */; };
|
||||
DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */; };
|
||||
DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5226EB1DF10058C060 /* BLEManager.swift */; };
|
||||
DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */; };
|
||||
DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5C26ED09490058C060 /* portnums.pb.swift */; };
|
||||
DDAF8C5F26ED09B50058C060 /* radioconfig.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5E26ED09B50058C060 /* radioconfig.pb.swift */; };
|
||||
DDAF8C6226ED0A230058C060 /* mqtt.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6026ED0A230058C060 /* mqtt.pb.swift */; };
|
||||
DDAF8C6326ED0A230058C060 /* admin.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6126ED0A230058C060 /* admin.pb.swift */; };
|
||||
DDAF8C6526ED0A490058C060 /* channel.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6426ED0A490058C060 /* channel.pb.swift */; };
|
||||
|
|
@ -109,10 +109,10 @@
|
|||
DD90860D26F69BAE00DC5189 /* NodeMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMap.swift; sourceTree = "<group>"; };
|
||||
DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalNotificationManager.swift; sourceTree = "<group>"; };
|
||||
DD9D8F2E2764403B00080993 /* CoreDataSample.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = CoreDataSample.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshPackets.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5226EB1DF10058C060 /* BLEManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManager.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mesh.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5C26ED09490058C060 /* portnums.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = portnums.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C5E26ED09B50058C060 /* radioconfig.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = radioconfig.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C6026ED0A230058C060 /* mqtt.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mqtt.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C6126ED0A230058C060 /* admin.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = admin.pb.swift; sourceTree = "<group>"; };
|
||||
DDAF8C6426ED0A490058C060 /* channel.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = channel.pb.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -237,7 +237,6 @@
|
|||
DD4C158B2824A91E0032668E /* module_config.pb.swift */,
|
||||
DDAF8C6026ED0A230058C060 /* mqtt.pb.swift */,
|
||||
DDAF8C5C26ED09490058C060 /* portnums.pb.swift */,
|
||||
DDAF8C5E26ED09B50058C060 /* radioconfig.pb.swift */,
|
||||
DDAF8C6626ED0C8C0058C060 /* remote_hardware.pb.swift */,
|
||||
DD17E5DC277D49D400010EC2 /* storeforward.pb.swift */,
|
||||
DDB2CC6D27F3EB47009C5FCC /* telemetry.pb.swift */,
|
||||
|
|
@ -371,6 +370,7 @@
|
|||
DDAF8C6D26ED19040058C060 /* Extensions.swift */,
|
||||
DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */,
|
||||
DD8169F8271F1A6100F4AB02 /* MeshLogger.swift */,
|
||||
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -547,7 +547,6 @@
|
|||
DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */,
|
||||
DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */,
|
||||
DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */,
|
||||
DDAF8C5F26ED09B50058C060 /* radioconfig.pb.swift in Sources */,
|
||||
DD5394FE276BA0EF00AD86B1 /* PositionEntityExtension.swift in Sources */,
|
||||
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */,
|
||||
DD4C158C2824A91E0032668E /* module_config.pb.swift in Sources */,
|
||||
|
|
@ -579,6 +578,7 @@
|
|||
DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */,
|
||||
DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */,
|
||||
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */,
|
||||
DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */,
|
||||
C9A88B57278B559900BD810A /* apponly.pb.swift in Sources */,
|
||||
DD4C158E2824AA7E0032668E /* config.pb.swift in Sources */,
|
||||
DD47E3D926F3093800029299 /* MessageBubble.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -171,12 +171,13 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
|
||||
|
||||
var peripheralName: String = peripheral.name ?? "Unknown"
|
||||
let last4Code: String = (peripheral.name != nil ? String(peripheral.name!.suffix(4)) : "Unknown")
|
||||
|
||||
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
|
||||
peripheralName = name
|
||||
}
|
||||
|
||||
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: String(peripheralName.suffix(3)), longName: peripheralName, firmwareVersion: "Unknown", rssi: RSSI.intValue, bitrate: nil, channelUtilization: nil, airTime: nil, lastUpdate: Date(), subscribed: false, peripheral: peripheral)
|
||||
let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, num: 0, name: peripheralName, shortName: String(peripheralName.suffix(3)), longName: peripheralName, lastFourCode: last4Code, firmwareVersion: "Unknown", rssi: RSSI.intValue, bitrate: nil, channelUtilization: nil, airTime: nil, lastUpdate: Date(), subscribed: false, peripheral: peripheral)
|
||||
let peripheralIndex = peripherals.firstIndex(where: { $0.id == newPeripheral.id })
|
||||
|
||||
if peripheralIndex != nil && newPeripheral.peripheral.state != CBPeripheralState.connected {
|
||||
|
|
@ -390,9 +391,54 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
|
||||
var decodedInfo = FromRadio()
|
||||
|
||||
decodedInfo = try! FromRadio(serializedData: characteristic.value!)
|
||||
|
||||
switch decodedInfo.packet.decoded.portnum {
|
||||
|
||||
case .unknownApp:
|
||||
print("MyInfo or NodeInfo")
|
||||
print("Sending nodeinfo: num=0x3b9c2510, lastseen=0, id=!3b9c2510, name=Unknown 2510")
|
||||
case .textMessageApp:
|
||||
textMessageAppPacket(packet: decodedInfo.packet, connectedNode: (self.connectedPeripheral != nil ? connectedPeripheral.num : 0), meshLogging: meshLoggingEnabled, context: context!)
|
||||
case .remoteHardwareApp:
|
||||
print("remoteHardwareApp")
|
||||
case .positionApp:
|
||||
print("positionApp")
|
||||
case .nodeinfoApp:
|
||||
print("nodeinfoApp")
|
||||
case .routingApp:
|
||||
routingPacket(packet: decodedInfo.packet, meshLogging: meshLoggingEnabled, context: context!)
|
||||
case .adminApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .replyApp:
|
||||
print("replyApp")
|
||||
case .ipTunnelApp:
|
||||
print("ipTunnelApp")
|
||||
case .serialApp:
|
||||
print("serialApp")
|
||||
case .storeForwardApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Store Forward App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .rangeTestApp:
|
||||
print("rangeTestApp")
|
||||
case .telemetryApp:
|
||||
telemetryPacket(packet: decodedInfo.packet, meshLogging: meshLoggingEnabled, context: context!)
|
||||
case .textMessageCompressedApp:
|
||||
print("textMessageCompressedApp")
|
||||
case .zpsApp:
|
||||
print("zpsApp")
|
||||
case .privateApp:
|
||||
print("privateApp")
|
||||
case .atakForwarder:
|
||||
print("atakForwarder")
|
||||
case .UNRECOGNIZED(_):
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Other App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for UNRECOGNIZED App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .max:
|
||||
print("MAX PORT NUM OF 511")
|
||||
}
|
||||
|
||||
// MARK: Incoming MyInfo Packet
|
||||
if decodedInfo.myInfo.myNodeNum != 0 {
|
||||
|
||||
|
|
@ -440,18 +486,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
print("💾 Saved the All - Broadcast User")
|
||||
}
|
||||
|
||||
//var settingsCalled = self.getSettings()
|
||||
|
||||
if false {
|
||||
|
||||
print("💾 Called Get Settings")
|
||||
|
||||
} else {
|
||||
|
||||
print("💥 Get Settings Call Failed")
|
||||
}
|
||||
|
||||
|
||||
} catch {
|
||||
|
||||
print("💥 Error Saving the All - Broadcast User")
|
||||
|
|
@ -690,300 +724,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if meshLoggingEnabled { MeshLogger.log("💾 BLE FROMRADIO received and nodeInfo saved for \(decodedInfo.nodeInfo.num)") }
|
||||
}
|
||||
}
|
||||
// Handle other packet types
|
||||
if decodedInfo.packet.id != 0 {
|
||||
|
||||
do {
|
||||
|
||||
// MARK: Incoming Packet from the TEXTMESSAGE_APP
|
||||
if decodedInfo.packet.decoded.portnum == PortNum.textMessageApp {
|
||||
|
||||
if let messageText = String(bytes: decodedInfo.packet.decoded.payload, encoding: .utf8) {
|
||||
|
||||
print("💬 BLE FROMRADIO received for text message app \(messageText)")
|
||||
if meshLoggingEnabled { MeshLogger.log("💬 BLE FROMRADIO received for text message app \(messageText)") }
|
||||
|
||||
let messageUsers: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
|
||||
messageUsers.predicate = NSPredicate(format: "num IN %@", [decodedInfo.packet.to, decodedInfo.packet.from])
|
||||
|
||||
do {
|
||||
|
||||
let fetchedUsers = try context?.fetch(messageUsers) as! [UserEntity]
|
||||
|
||||
let newMessage = MessageEntity(context: context!)
|
||||
newMessage.messageId = Int64(decodedInfo.packet.id)
|
||||
newMessage.messageTimestamp = Int32(bitPattern: decodedInfo.packet.rxTime)
|
||||
newMessage.receivedACK = false
|
||||
newMessage.direction = "IN"
|
||||
newMessage.isEmoji = decodedInfo.packet.decoded.emoji == 1
|
||||
|
||||
if decodedInfo.packet.decoded.replyID > 0 {
|
||||
|
||||
newMessage.replyID = Int64(decodedInfo.packet.decoded.replyID)
|
||||
}
|
||||
|
||||
if decodedInfo.packet.to == broadcastNodeNum && fetchedUsers.count == 1 {
|
||||
|
||||
// Save the broadcast user if it does not exist
|
||||
let bcu: UserEntity = UserEntity(context: context!)
|
||||
bcu.shortName = "ALL"
|
||||
bcu.longName = "All - Broadcast"
|
||||
bcu.hwModel = "UNSET"
|
||||
bcu.num = Int64(broadcastNodeNum)
|
||||
bcu.userId = "BROADCASTNODE"
|
||||
newMessage.toUser = bcu
|
||||
|
||||
} else {
|
||||
|
||||
newMessage.toUser = fetchedUsers.first(where: { $0.num == decodedInfo.packet.to })
|
||||
}
|
||||
|
||||
newMessage.fromUser = fetchedUsers.first(where: { $0.num == decodedInfo.packet.from })
|
||||
newMessage.messagePayload = messageText
|
||||
|
||||
do {
|
||||
|
||||
try context!.save()
|
||||
print("💾 Saved a new message for \(decodedInfo.packet.id)")
|
||||
if meshLoggingEnabled { MeshLogger.log("💾 Saved a new message for \(newMessage.messageId)") }
|
||||
|
||||
if newMessage.toUser != nil && newMessage.toUser!.num == self.broadcastNodeNum || self.connectedPeripheral != nil && self.connectedPeripheral.num == newMessage.toUser!.num {
|
||||
|
||||
// Create an iOS Notification for the received message and schedule it immediately
|
||||
let manager = LocalNotificationManager()
|
||||
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: ("notification.id.\(newMessage.messageId)"),
|
||||
title: "\(newMessage.fromUser?.longName ?? "Unknown")",
|
||||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "???")",
|
||||
content: messageText)
|
||||
]
|
||||
manager.schedule()
|
||||
if meshLoggingEnabled { MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown") \(messageText)") }
|
||||
|
||||
}
|
||||
} catch {
|
||||
|
||||
context!.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Failed to save new MessageEntity \(nsError)")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
print("💥 Fetch Message To and From Users Error")
|
||||
}
|
||||
}
|
||||
// MARK: Incoming NODEINFO_APP Packet
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.nodeinfoApp {
|
||||
|
||||
let fetchNodeInfoAppRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodeInfoAppRequest.predicate = NSPredicate(format: "num == %lld", Int64(decodedInfo.packet.from))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context?.fetch(fetchNodeInfoAppRequest) as! [NodeInfoEntity]
|
||||
|
||||
if fetchedNode.count == 1 {
|
||||
fetchedNode[0].id = Int64(decodedInfo.packet.from)
|
||||
fetchedNode[0].num = Int64(decodedInfo.packet.from)
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(decodedInfo.packet.rxTime)))
|
||||
fetchedNode[0].snr = decodedInfo.packet.rxSnr
|
||||
|
||||
} else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
|
||||
try context!.save()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("💾 Updated NodeInfo SNR \(decodedInfo.packet.rxSnr) and Time from Node Info App Packet For: \(fetchedNode[0].num)")}
|
||||
print("💾 Updated NodeInfo SNR \(decodedInfo.packet.rxSnr) and Time from Packet For: \(fetchedNode[0].num)")
|
||||
|
||||
} catch {
|
||||
|
||||
context!.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
|
||||
|
||||
}
|
||||
} catch {
|
||||
|
||||
print("💥 Error Fetching NodeInfoEntity for NODEINFO_APP")
|
||||
}
|
||||
|
||||
// MARK: Incoming Packet from the POSITION_APP
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.positionApp {
|
||||
let fetchNodePositionRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodePositionRequest.predicate = NSPredicate(format: "num == %lld", Int64(decodedInfo.packet.from))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context?.fetch(fetchNodePositionRequest) as! [NodeInfoEntity]
|
||||
|
||||
if fetchedNode.count == 1 {
|
||||
fetchedNode[0].id = Int64(decodedInfo.packet.from)
|
||||
fetchedNode[0].num = Int64(decodedInfo.packet.from)
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(decodedInfo.packet.rxTime)))
|
||||
fetchedNode[0].snr = decodedInfo.packet.rxSnr
|
||||
|
||||
if let positionMessage = try? Position(serializedData: decodedInfo.packet.decoded.payload) {
|
||||
|
||||
let position = PositionEntity(context: context!)
|
||||
position.latitudeI = positionMessage.latitudeI
|
||||
position.longitudeI = positionMessage.longitudeI
|
||||
position.altitude = positionMessage.altitude
|
||||
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
|
||||
|
||||
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
|
||||
mutablePositions.add(position)
|
||||
|
||||
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return
|
||||
}
|
||||
do {
|
||||
|
||||
try context!.save()
|
||||
|
||||
if meshLoggingEnabled {
|
||||
MeshLogger.log("💾 Updated NodeInfo Position Coordinates, SNR \(decodedInfo.packet.rxSnr) and Time from Position App Packet For: \(fetchedNode[0].num)")
|
||||
}
|
||||
print("💾 Updated NodeInfo Position Coordinates, SNR \(decodedInfo.packet.rxSnr) and Time from Position App Packet For:: \(fetchedNode[0].num)")
|
||||
|
||||
} catch {
|
||||
|
||||
context!.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving NodeInfoEntity from POSITION_APP \(nsError)")
|
||||
}
|
||||
} catch {
|
||||
|
||||
print("💥 Error Fetching NodeInfoEntity for POSITION_APP")
|
||||
}
|
||||
// MARK: Incoming ROUTING_APP Packet
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.routingApp {
|
||||
|
||||
|
||||
if let routingMessage = try? Routing(serializedData: decodedInfo.packet.decoded.payload) {
|
||||
print(decodedInfo.packet.decoded.requestID)
|
||||
print(routingMessage)
|
||||
|
||||
let error = routingMessage.errorReason
|
||||
|
||||
var errorExplanation = "Unknown Routing Error"
|
||||
|
||||
switch error {
|
||||
case Routing.Error.none:
|
||||
errorExplanation = "This message is not a failure"
|
||||
case Routing.Error.noRoute:
|
||||
errorExplanation = "Our node doesn't have a route to the requested destination anymore."
|
||||
case Routing.Error.gotNak:
|
||||
errorExplanation = "We received a nak while trying to forward on your behalf"
|
||||
case Routing.Error.timeout:
|
||||
errorExplanation = "Timeout"
|
||||
case Routing.Error.noInterface:
|
||||
errorExplanation = "No suitable interface could be found for delivering this packet"
|
||||
case Routing.Error.maxRetransmit:
|
||||
errorExplanation = "We reached the max retransmission count (typically for naive flood routing)"
|
||||
case Routing.Error.noChannel:
|
||||
errorExplanation = "No suitable channel was found for sending this packet (i.e. was requested channel index disabled?)"
|
||||
case Routing.Error.tooLarge:
|
||||
errorExplanation = "The packet was too big for sending (exceeds interface MTU after encoding)"
|
||||
case Routing.Error.noResponse:
|
||||
errorExplanation = "The request had want_response set, the request reached the destination node, but no service on that node wants to send a response (possibly due to bad channel permissions)"
|
||||
case Routing.Error.badRequest:
|
||||
errorExplanation = "The application layer service on the remote node received your request, but considered your request somehow invalid"
|
||||
case Routing.Error.notAuthorized:
|
||||
errorExplanation = "The application layer service on the remote node received your request, but considered your request not authorized (i.e you did not send the request on the required bound channel)"
|
||||
fallthrough
|
||||
default:
|
||||
print(error)
|
||||
}
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🕸️ ROUTING PACKET received for RequestID: \(decodedInfo.packet.decoded.requestID) Error: \(errorExplanation)") }
|
||||
print("🕸️ ROUTING PACKET received for RequestID: \(decodedInfo.packet.decoded.requestID) Error: \(errorExplanation)")
|
||||
|
||||
|
||||
if routingMessage.errorReason == Routing.Error.none {
|
||||
|
||||
print("Priority ACK no Error")
|
||||
|
||||
let fetchMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
|
||||
fetchMessageRequest.predicate = NSPredicate(format: "messageId == %lld", Int64(decodedInfo.packet.decoded.requestID))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedMessage = try context?.fetch(fetchMessageRequest)[0] as? MessageEntity
|
||||
|
||||
if fetchedMessage != nil {
|
||||
|
||||
fetchedMessage!.receivedACK = true
|
||||
fetchedMessage!.ackSNR = decodedInfo.packet.rxSnr
|
||||
fetchedMessage!.ackTimestamp = Int32(decodedInfo.packet.rxTime)
|
||||
fetchedMessage!.objectWillChange.send()
|
||||
}
|
||||
|
||||
try context!.save()
|
||||
|
||||
if meshLoggingEnabled {
|
||||
MeshLogger.log("💾 ACK Received and saved for MessageID \(decodedInfo.packet.decoded.requestID)")
|
||||
}
|
||||
print("💾 ACK Received and saved for MessageID \(decodedInfo.packet.decoded.requestID)")
|
||||
|
||||
} catch {
|
||||
|
||||
context!.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving ACK for message MessageID \(decodedInfo.packet.id) Error: \(nsError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Incoming TELEMETRY_APP Packet
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.telemetryApp {
|
||||
|
||||
|
||||
if let telemetryMessage = try? Telemetry(serializedData: decodedInfo.packet.decoded.payload) {
|
||||
|
||||
let telemetry = TelemetryEntity(context: context!)
|
||||
print(decodedInfo.packet.decoded.requestID)
|
||||
print(telemetryMessage)
|
||||
}
|
||||
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Telemetry App UNHANDLED \(try decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Telemetry App UNHANDLED \(try decodedInfo.packet.jsonString())")
|
||||
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.storeForwardApp {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Store Forward App UNHANDLED \(try decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())")
|
||||
|
||||
} else if decodedInfo.packet.decoded.portnum == PortNum.adminApp {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try decodedInfo.packet.jsonString())")
|
||||
|
||||
} else {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Other App UNHANDLED \(try decodedInfo.packet.jsonString())") }
|
||||
print("ℹ️ MESH PACKET received for Other App UNHANDLED \(try decodedInfo.packet.jsonString())")
|
||||
}
|
||||
|
||||
} catch {
|
||||
if meshLoggingEnabled { MeshLogger.log("⚰️ Fatal Error: Failed to decode json") }
|
||||
print("⚰️ Fatal Error: Failed to decode json")
|
||||
}
|
||||
}
|
||||
|
||||
if decodedInfo.configCompleteID != 0 {
|
||||
|
||||
|
|
@ -994,20 +735,14 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
|
||||
case FROMNUM_UUID :
|
||||
print("🚨 FROMNUM Characteristic UUID: \(characteristic.uuid)")
|
||||
if characteristic.value == nil || characteristic.value!.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
print("FROMNUM Notification, value will be read below")
|
||||
|
||||
var decodedInfo = FromRadio()
|
||||
|
||||
//decodedInfo = try! FromRadio(serializedData: characteristic.value!)
|
||||
|
||||
default:
|
||||
print("🚨 Unhandled Characteristic UUID: \(characteristic.uuid)")
|
||||
}
|
||||
peripheral.readValue(for: FROMRADIO_characteristic)
|
||||
}
|
||||
peripheral.readValue(for: FROMRADIO_characteristic)
|
||||
}
|
||||
|
||||
// Send Message
|
||||
public func sendMessage(message: String, toUserNum: Int64, isEmoji: Bool, replyID: Int64) -> Bool {
|
||||
|
|
@ -1116,6 +851,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
print("💾 Saved a new sent message to \(toUserNum)")
|
||||
if meshLoggingEnabled { MeshLogger.log("💾 Saved a new sent message from \(connectedPeripheral.num) to \(toUserNum)") }
|
||||
success = true
|
||||
//sendShutdown(destNum: connectedPeripheral.num, wantResponse: true)
|
||||
|
||||
} catch {
|
||||
|
||||
|
|
@ -1165,7 +901,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
var meshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(destNum)
|
||||
meshPacket.from = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.wantAck = wantResponse
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1179,13 +915,14 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
toRadio.packet = meshPacket
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Position Packet from the phone to the device for node: \(fromNodeNum)") }
|
||||
print("📍 Sent a Position Packet from the phone to the device for node: \(fromNodeNum)")
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Position Packet from the Apple device GPS to node: \(fromNodeNum)") }
|
||||
print("📍 Sent a Position Packet from the Apple device GPS to node: \(fromNodeNum)")
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
success = true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1218,7 +955,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
public func getSettings() -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
//adminPacket.getRadioRequest = true
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
|
|
@ -1249,4 +985,41 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
// Send Position
|
||||
public func sendShutdown(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.rebootSeconds = 30
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = false
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
283
MeshtasticClient/Helpers/MeshPackets.swift
Normal file
283
MeshtasticClient/Helpers/MeshPackets.swift
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
//
|
||||
// MeshPackets.swift
|
||||
// Meshtastic Apple
|
||||
//
|
||||
// Created by Garth Vander Houwen on 5/27/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
func nodeInfoPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
let fetchNodeInfoAppRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodeInfoAppRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context.fetch(fetchNodeInfoAppRequest) as! [NodeInfoEntity]
|
||||
|
||||
if fetchedNode.count == 1 {
|
||||
fetchedNode[0].id = Int64(packet.from)
|
||||
fetchedNode[0].num = Int64(packet.from)
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
|
||||
fetchedNode[0].snr = packet.rxSnr
|
||||
|
||||
} else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
|
||||
if meshLogging { MeshLogger.log("💾 Updated NodeInfo SNR \(packet.rxSnr) and Time from Node Info App Packet For: \(fetchedNode[0].num)")}
|
||||
print("💾 Updated NodeInfo SNR \(packet.rxSnr) and Time from Packet For: \(fetchedNode[0].num)")
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving NodeInfoEntity from NODEINFO_APP \(nsError)")
|
||||
|
||||
}
|
||||
} catch {
|
||||
|
||||
print("💥 Error Fetching NodeInfoEntity for NODEINFO_APP")
|
||||
}
|
||||
}
|
||||
|
||||
func positionPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
let fetchNodePositionRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNodePositionRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context.fetch(fetchNodePositionRequest) as! [NodeInfoEntity]
|
||||
|
||||
if fetchedNode.count == 1 {
|
||||
|
||||
fetchedNode[0].id = Int64(packet.from)
|
||||
fetchedNode[0].num = Int64(packet.from)
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
|
||||
fetchedNode[0].snr = packet.rxSnr
|
||||
|
||||
if let positionMessage = try? Position(serializedData: packet.decoded.payload) {
|
||||
|
||||
let position = PositionEntity(context: context)
|
||||
position.latitudeI = positionMessage.latitudeI
|
||||
position.longitudeI = positionMessage.longitudeI
|
||||
position.altitude = positionMessage.altitude
|
||||
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
|
||||
|
||||
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
|
||||
mutablePositions.add(position)
|
||||
|
||||
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return
|
||||
}
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
|
||||
if meshLogging {
|
||||
MeshLogger.log("💾 Updated NodeInfo Position Coordinates, SNR \(packet.rxSnr) and Time from Position App Packet For: \(fetchedNode[0].num)")
|
||||
}
|
||||
print("💾 Updated NodeInfo Position Coordinates, SNR \(packet.rxSnr) and Time from Position App Packet For: \(fetchedNode[0].num)")
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving NodeInfoEntity from POSITION_APP \(nsError)")
|
||||
}
|
||||
} catch {
|
||||
|
||||
print("💥 Error Fetching NodeInfoEntity for POSITION_APP")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func routingPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
if let routingMessage = try? Routing(serializedData: packet.decoded.payload) {
|
||||
print(packet.decoded.requestID)
|
||||
print(routingMessage)
|
||||
|
||||
let error = routingMessage.errorReason
|
||||
|
||||
var errorExplanation = "Unknown Routing Error"
|
||||
|
||||
switch error {
|
||||
case Routing.Error.none:
|
||||
errorExplanation = "This message is not a failure"
|
||||
case Routing.Error.noRoute:
|
||||
errorExplanation = "Our node doesn't have a route to the requested destination anymore."
|
||||
case Routing.Error.gotNak:
|
||||
errorExplanation = "We received a nak while trying to forward on your behalf"
|
||||
case Routing.Error.timeout:
|
||||
errorExplanation = "Timeout"
|
||||
case Routing.Error.noInterface:
|
||||
errorExplanation = "No suitable interface could be found for delivering this packet"
|
||||
case Routing.Error.maxRetransmit:
|
||||
errorExplanation = "We reached the max retransmission count (typically for naive flood routing)"
|
||||
case Routing.Error.noChannel:
|
||||
errorExplanation = "No suitable channel was found for sending this packet (i.e. was requested channel index disabled?)"
|
||||
case Routing.Error.tooLarge:
|
||||
errorExplanation = "The packet was too big for sending (exceeds interface MTU after encoding)"
|
||||
case Routing.Error.noResponse:
|
||||
errorExplanation = "The request had want_response set, the request reached the destination node, but no service on that node wants to send a response (possibly due to bad channel permissions)"
|
||||
case Routing.Error.badRequest:
|
||||
errorExplanation = "The application layer service on the remote node received your request, but considered your request somehow invalid"
|
||||
case Routing.Error.notAuthorized:
|
||||
errorExplanation = "The application layer service on the remote node received your request, but considered your request not authorized (i.e you did not send the request on the required bound channel)"
|
||||
fallthrough
|
||||
default:
|
||||
print(error)
|
||||
}
|
||||
|
||||
if meshLogging { MeshLogger.log("🕸️ ROUTING PACKET received for RequestID: \(packet.decoded.requestID) Error: \(errorExplanation)") }
|
||||
print("🕸️ ROUTING PACKET received for RequestID: \(packet.decoded.requestID) Error: \(errorExplanation)")
|
||||
|
||||
if routingMessage.errorReason == Routing.Error.none {
|
||||
|
||||
print("Priority ACK no Error")
|
||||
|
||||
let fetchMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
|
||||
fetchMessageRequest.predicate = NSPredicate(format: "messageId == %lld", Int64(packet.decoded.requestID))
|
||||
|
||||
do {
|
||||
|
||||
let fetchedMessage = try context.fetch(fetchMessageRequest)[0] as? MessageEntity
|
||||
|
||||
if fetchedMessage != nil {
|
||||
|
||||
fetchedMessage!.receivedACK = true
|
||||
fetchedMessage!.ackSNR = packet.rxSnr
|
||||
fetchedMessage!.ackTimestamp = Int32(packet.rxTime)
|
||||
fetchedMessage!.objectWillChange.send()
|
||||
}
|
||||
|
||||
try context.save()
|
||||
|
||||
if meshLogging {
|
||||
MeshLogger.log("💾 ACK Received and saved for MessageID \(packet.decoded.requestID)")
|
||||
}
|
||||
print("💾 ACK Received and saved for MessageID \(packet.decoded.requestID)")
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving ACK for message MessageID \(packet.id) Error: \(nsError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func telemetryPacket(packet: MeshPacket, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
if let telemetryMessage = try? Telemetry(serializedData: packet.decoded.payload) {
|
||||
|
||||
let telemetry = TelemetryEntity(context: context)
|
||||
print(packet.decoded.requestID)
|
||||
|
||||
if meshLogging { MeshLogger.log("ℹ️ MESH PACKET received for Telemetry App UNHANDLED \(telemetryMessage)") }
|
||||
print("ℹ️ MESH PACKET received for Telemetry App UNHANDLED \(telemetryMessage)")
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
let broadcastNodeNum: UInt32 = 4294967295
|
||||
|
||||
if let messageText = String(bytes: packet.decoded.payload, encoding: .utf8) {
|
||||
|
||||
print("💬 BLE FROMRADIO received for text message app \(messageText)")
|
||||
if meshLogging { MeshLogger.log("💬 BLE FROMRADIO received for text message app \(messageText)") }
|
||||
|
||||
let messageUsers: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
|
||||
messageUsers.predicate = NSPredicate(format: "num IN %@", [packet.to, packet.from])
|
||||
|
||||
do {
|
||||
|
||||
let fetchedUsers = try context.fetch(messageUsers) as! [UserEntity]
|
||||
|
||||
let newMessage = MessageEntity(context: context)
|
||||
newMessage.messageId = Int64(packet.id)
|
||||
newMessage.messageTimestamp = Int32(bitPattern: packet.rxTime)
|
||||
newMessage.receivedACK = false
|
||||
newMessage.direction = "IN"
|
||||
newMessage.isEmoji = packet.decoded.emoji == 1
|
||||
|
||||
if packet.decoded.replyID > 0 {
|
||||
|
||||
newMessage.replyID = Int64(packet.decoded.replyID)
|
||||
}
|
||||
|
||||
if packet.to == broadcastNodeNum && fetchedUsers.count == 1 {
|
||||
|
||||
// Save the broadcast user if it does not exist
|
||||
let bcu: UserEntity = UserEntity(context: context)
|
||||
bcu.shortName = "ALL"
|
||||
bcu.longName = "All - Broadcast"
|
||||
bcu.hwModel = "UNSET"
|
||||
bcu.num = Int64(broadcastNodeNum)
|
||||
bcu.userId = "BROADCASTNODE"
|
||||
newMessage.toUser = bcu
|
||||
|
||||
} else {
|
||||
|
||||
newMessage.toUser = fetchedUsers.first(where: { $0.num == packet.to })
|
||||
}
|
||||
|
||||
newMessage.fromUser = fetchedUsers.first(where: { $0.num == packet.from })
|
||||
newMessage.messagePayload = messageText
|
||||
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
print("💾 Saved a new message for \(packet.id)")
|
||||
if meshLogging { MeshLogger.log("💾 Saved a new message for \(newMessage.messageId)") }
|
||||
|
||||
if newMessage.toUser != nil && newMessage.toUser!.num == broadcastNodeNum || connectedNode == newMessage.toUser!.num {
|
||||
|
||||
// Create an iOS Notification for the received message and schedule it immediately
|
||||
let manager = LocalNotificationManager()
|
||||
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: ("notification.id.\(newMessage.messageId)"),
|
||||
title: "\(newMessage.fromUser?.longName ?? "Unknown")",
|
||||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "???")",
|
||||
content: messageText)
|
||||
]
|
||||
manager.schedule()
|
||||
if meshLogging { MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown") \(messageText)") }
|
||||
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Failed to save new MessageEntity \(nsError)")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
print("💥 Fetch Message To and From Users Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ struct Peripheral: Identifiable {
|
|||
var name: String
|
||||
var shortName: String
|
||||
var longName: String
|
||||
var lastFourCode: String
|
||||
var firmwareVersion: String
|
||||
var rssi: Int
|
||||
var bitrate: Float?
|
||||
|
|
@ -16,12 +17,13 @@ struct Peripheral: Identifiable {
|
|||
var subscribed: Bool
|
||||
var peripheral: CBPeripheral
|
||||
|
||||
init(id: String, num: Int64, name: String, shortName: String, longName: String, firmwareVersion: String, rssi: Int, bitrate: Float?, channelUtilization: Float?, airTime: Float?, lastUpdate: Date, subscribed: Bool, peripheral: CBPeripheral) {
|
||||
init(id: String, num: Int64, name: String, shortName: String, longName: String, lastFourCode: String, firmwareVersion: String, rssi: Int, bitrate: Float?, channelUtilization: Float?, airTime: Float?, lastUpdate: Date, subscribed: Bool, peripheral: CBPeripheral) {
|
||||
self.id = id
|
||||
self.num = num
|
||||
self.name = name
|
||||
self.shortName = shortName
|
||||
self.longName = longName
|
||||
self.lastFourCode = lastFourCode
|
||||
self.firmwareVersion = firmwareVersion
|
||||
self.rssi = rssi
|
||||
self.bitrate = bitrate
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class PersistenceController {
|
|||
init(inMemory: Bool = false) {
|
||||
|
||||
container = NSPersistentContainer(name: "Meshtastic")
|
||||
//self.clearDatabase()
|
||||
//Likeself.clearDatabase()
|
||||
|
||||
if inMemory {
|
||||
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ struct Config {
|
|||
var positionBroadcastSecs: UInt32 = 0
|
||||
|
||||
///
|
||||
/// We should send our position this often (but only if it has changed significantly)
|
||||
/// Disable adaptive position braoadcast, which is now the default.
|
||||
var positionBroadcastSmartDisabled: Bool = false
|
||||
|
||||
///
|
||||
|
|
@ -266,10 +266,6 @@ struct Config {
|
|||
/// The lat/lon/alt can be set by an internal GPS or with the help of the app.
|
||||
var fixedPosition: Bool = false
|
||||
|
||||
///
|
||||
/// Should we disbale location sharing with other nodes (or the local phone)
|
||||
var locationShareDisabled: Bool = false
|
||||
|
||||
///
|
||||
/// Should the GPS be disabled for this node?
|
||||
var gpsDisabled: Bool = false
|
||||
|
|
@ -618,6 +614,10 @@ struct Config {
|
|||
/// will be a station
|
||||
var apMode: Bool = false
|
||||
|
||||
///
|
||||
/// If set, the node AP will broadcast as a hidden SSID
|
||||
var apHidden: Bool = false
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
|
@ -738,7 +738,7 @@ struct Config {
|
|||
/// Because protobufs take ZERO space when the value is zero this works out nicely.
|
||||
/// This value is replaced by bandwidth/spread_factor/coding_rate.
|
||||
/// If you'd like to experiment with other options add them to MeshRadio.cpp in the device code.
|
||||
var modemPreset: Config.LoRaConfig.ModemPreset = .vlongSlow
|
||||
var modemPreset: Config.LoRaConfig.ModemPreset = .longFast
|
||||
|
||||
///
|
||||
/// Bandwidth in MHz
|
||||
|
|
@ -898,7 +898,7 @@ struct Config {
|
|||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case vlongSlow // = 0
|
||||
case longFast // = 0
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
|
|
@ -906,7 +906,7 @@ struct Config {
|
|||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case longFast // = 2
|
||||
case vlongSlow // = 2
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
|
|
@ -926,14 +926,14 @@ struct Config {
|
|||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
self = .vlongSlow
|
||||
self = .longFast
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .vlongSlow
|
||||
case 0: self = .longFast
|
||||
case 1: self = .longSlow
|
||||
case 2: self = .longFast
|
||||
case 2: self = .vlongSlow
|
||||
case 3: self = .midSlow
|
||||
case 4: self = .midFast
|
||||
case 5: self = .shortSlow
|
||||
|
|
@ -944,9 +944,9 @@ struct Config {
|
|||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .vlongSlow: return 0
|
||||
case .longFast: return 0
|
||||
case .longSlow: return 1
|
||||
case .longFast: return 2
|
||||
case .vlongSlow: return 2
|
||||
case .midSlow: return 3
|
||||
case .midFast: return 4
|
||||
case .shortSlow: return 5
|
||||
|
|
@ -1047,9 +1047,9 @@ extension Config.LoRaConfig.RegionCode: CaseIterable {
|
|||
extension Config.LoRaConfig.ModemPreset: CaseIterable {
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [Config.LoRaConfig.ModemPreset] = [
|
||||
.vlongSlow,
|
||||
.longSlow,
|
||||
.longFast,
|
||||
.longSlow,
|
||||
.vlongSlow,
|
||||
.midSlow,
|
||||
.midFast,
|
||||
.shortSlow,
|
||||
|
|
@ -1291,7 +1291,6 @@ extension Config.PositionConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
1: .standard(proto: "position_broadcast_secs"),
|
||||
2: .standard(proto: "position_broadcast_smart_disabled"),
|
||||
3: .standard(proto: "fixed_position"),
|
||||
4: .standard(proto: "location_share_disabled"),
|
||||
5: .standard(proto: "gps_disabled"),
|
||||
6: .standard(proto: "gps_update_interval"),
|
||||
7: .standard(proto: "gps_attempt_time"),
|
||||
|
|
@ -1309,7 +1308,6 @@ extension Config.PositionConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.positionBroadcastSecs) }()
|
||||
case 2: try { try decoder.decodeSingularBoolField(value: &self.positionBroadcastSmartDisabled) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.fixedPosition) }()
|
||||
case 4: try { try decoder.decodeSingularBoolField(value: &self.locationShareDisabled) }()
|
||||
case 5: try { try decoder.decodeSingularBoolField(value: &self.gpsDisabled) }()
|
||||
case 6: try { try decoder.decodeSingularUInt32Field(value: &self.gpsUpdateInterval) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &self.gpsAttemptTime) }()
|
||||
|
|
@ -1331,9 +1329,6 @@ extension Config.PositionConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
if self.fixedPosition != false {
|
||||
try visitor.visitSingularBoolField(value: self.fixedPosition, fieldNumber: 3)
|
||||
}
|
||||
if self.locationShareDisabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.locationShareDisabled, fieldNumber: 4)
|
||||
}
|
||||
if self.gpsDisabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.gpsDisabled, fieldNumber: 5)
|
||||
}
|
||||
|
|
@ -1359,7 +1354,6 @@ extension Config.PositionConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
if lhs.positionBroadcastSecs != rhs.positionBroadcastSecs {return false}
|
||||
if lhs.positionBroadcastSmartDisabled != rhs.positionBroadcastSmartDisabled {return false}
|
||||
if lhs.fixedPosition != rhs.fixedPosition {return false}
|
||||
if lhs.locationShareDisabled != rhs.locationShareDisabled {return false}
|
||||
if lhs.gpsDisabled != rhs.gpsDisabled {return false}
|
||||
if lhs.gpsUpdateInterval != rhs.gpsUpdateInterval {return false}
|
||||
if lhs.gpsAttemptTime != rhs.gpsAttemptTime {return false}
|
||||
|
|
@ -1511,6 +1505,7 @@ extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
1: .same(proto: "ssid"),
|
||||
2: .same(proto: "psk"),
|
||||
3: .standard(proto: "ap_mode"),
|
||||
4: .standard(proto: "ap_hidden"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1522,6 +1517,7 @@ extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
case 1: try { try decoder.decodeSingularStringField(value: &self.ssid) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.psk) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.apMode) }()
|
||||
case 4: try { try decoder.decodeSingularBoolField(value: &self.apHidden) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1537,6 +1533,9 @@ extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
if self.apMode != false {
|
||||
try visitor.visitSingularBoolField(value: self.apMode, fieldNumber: 3)
|
||||
}
|
||||
if self.apHidden != false {
|
||||
try visitor.visitSingularBoolField(value: self.apHidden, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1544,6 +1543,7 @@ extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
if lhs.ssid != rhs.ssid {return false}
|
||||
if lhs.psk != rhs.psk {return false}
|
||||
if lhs.apMode != rhs.apMode {return false}
|
||||
if lhs.apHidden != rhs.apHidden {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -1644,7 +1644,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
if self.txPower != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.txPower, fieldNumber: 1)
|
||||
}
|
||||
if self.modemPreset != .vlongSlow {
|
||||
if self.modemPreset != .longFast {
|
||||
try visitor.visitSingularEnumField(value: self.modemPreset, fieldNumber: 2)
|
||||
}
|
||||
if self.bandwidth != 0 {
|
||||
|
|
@ -1710,9 +1710,9 @@ extension Config.LoRaConfig.RegionCode: SwiftProtobuf._ProtoNameProviding {
|
|||
|
||||
extension Config.LoRaConfig.ModemPreset: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "VLongSlow"),
|
||||
0: .same(proto: "LongFast"),
|
||||
1: .same(proto: "LongSlow"),
|
||||
2: .same(proto: "LongFast"),
|
||||
2: .same(proto: "VLongSlow"),
|
||||
3: .same(proto: "MidSlow"),
|
||||
4: .same(proto: "MidFast"),
|
||||
5: .same(proto: "ShortSlow"),
|
||||
|
|
|
|||
|
|
@ -215,11 +215,180 @@ struct OEMStore {
|
|||
init() {}
|
||||
}
|
||||
|
||||
struct LocalConfig {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var device: Config.DeviceConfig {
|
||||
get {return _storage._device ?? Config.DeviceConfig()}
|
||||
set {_uniqueStorage()._device = newValue}
|
||||
}
|
||||
/// Returns true if `device` has been explicitly set.
|
||||
var hasDevice: Bool {return _storage._device != nil}
|
||||
/// Clears the value of `device`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDevice() {_uniqueStorage()._device = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var position: Config.PositionConfig {
|
||||
get {return _storage._position ?? Config.PositionConfig()}
|
||||
set {_uniqueStorage()._position = newValue}
|
||||
}
|
||||
/// Returns true if `position` has been explicitly set.
|
||||
var hasPosition: Bool {return _storage._position != nil}
|
||||
/// Clears the value of `position`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPosition() {_uniqueStorage()._position = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var power: Config.PowerConfig {
|
||||
get {return _storage._power ?? Config.PowerConfig()}
|
||||
set {_uniqueStorage()._power = newValue}
|
||||
}
|
||||
/// Returns true if `power` has been explicitly set.
|
||||
var hasPower: Bool {return _storage._power != nil}
|
||||
/// Clears the value of `power`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPower() {_uniqueStorage()._power = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var wifi: Config.WiFiConfig {
|
||||
get {return _storage._wifi ?? Config.WiFiConfig()}
|
||||
set {_uniqueStorage()._wifi = newValue}
|
||||
}
|
||||
/// Returns true if `wifi` has been explicitly set.
|
||||
var hasWifi: Bool {return _storage._wifi != nil}
|
||||
/// Clears the value of `wifi`. Subsequent reads from it will return its default value.
|
||||
mutating func clearWifi() {_uniqueStorage()._wifi = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var display: Config.DisplayConfig {
|
||||
get {return _storage._display ?? Config.DisplayConfig()}
|
||||
set {_uniqueStorage()._display = newValue}
|
||||
}
|
||||
/// Returns true if `display` has been explicitly set.
|
||||
var hasDisplay: Bool {return _storage._display != nil}
|
||||
/// Clears the value of `display`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDisplay() {_uniqueStorage()._display = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var lora: Config.LoRaConfig {
|
||||
get {return _storage._lora ?? Config.LoRaConfig()}
|
||||
set {_uniqueStorage()._lora = newValue}
|
||||
}
|
||||
/// Returns true if `lora` has been explicitly set.
|
||||
var hasLora: Bool {return _storage._lora != nil}
|
||||
/// Clears the value of `lora`. Subsequent reads from it will return its default value.
|
||||
mutating func clearLora() {_uniqueStorage()._lora = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
struct LocalModuleConfig {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var mqtt: ModuleConfig.MQTTConfig {
|
||||
get {return _storage._mqtt ?? ModuleConfig.MQTTConfig()}
|
||||
set {_uniqueStorage()._mqtt = newValue}
|
||||
}
|
||||
/// Returns true if `mqtt` has been explicitly set.
|
||||
var hasMqtt: Bool {return _storage._mqtt != nil}
|
||||
/// Clears the value of `mqtt`. Subsequent reads from it will return its default value.
|
||||
mutating func clearMqtt() {_uniqueStorage()._mqtt = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var serial: ModuleConfig.SerialConfig {
|
||||
get {return _storage._serial ?? ModuleConfig.SerialConfig()}
|
||||
set {_uniqueStorage()._serial = newValue}
|
||||
}
|
||||
/// Returns true if `serial` has been explicitly set.
|
||||
var hasSerial: Bool {return _storage._serial != nil}
|
||||
/// Clears the value of `serial`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSerial() {_uniqueStorage()._serial = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var externalNotification: ModuleConfig.ExternalNotificationConfig {
|
||||
get {return _storage._externalNotification ?? ModuleConfig.ExternalNotificationConfig()}
|
||||
set {_uniqueStorage()._externalNotification = newValue}
|
||||
}
|
||||
/// Returns true if `externalNotification` has been explicitly set.
|
||||
var hasExternalNotification: Bool {return _storage._externalNotification != nil}
|
||||
/// Clears the value of `externalNotification`. Subsequent reads from it will return its default value.
|
||||
mutating func clearExternalNotification() {_uniqueStorage()._externalNotification = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var storeForward: ModuleConfig.StoreForwardConfig {
|
||||
get {return _storage._storeForward ?? ModuleConfig.StoreForwardConfig()}
|
||||
set {_uniqueStorage()._storeForward = newValue}
|
||||
}
|
||||
/// Returns true if `storeForward` has been explicitly set.
|
||||
var hasStoreForward: Bool {return _storage._storeForward != nil}
|
||||
/// Clears the value of `storeForward`. Subsequent reads from it will return its default value.
|
||||
mutating func clearStoreForward() {_uniqueStorage()._storeForward = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var rangeTest: ModuleConfig.RangeTestConfig {
|
||||
get {return _storage._rangeTest ?? ModuleConfig.RangeTestConfig()}
|
||||
set {_uniqueStorage()._rangeTest = newValue}
|
||||
}
|
||||
/// Returns true if `rangeTest` has been explicitly set.
|
||||
var hasRangeTest: Bool {return _storage._rangeTest != nil}
|
||||
/// Clears the value of `rangeTest`. Subsequent reads from it will return its default value.
|
||||
mutating func clearRangeTest() {_uniqueStorage()._rangeTest = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var telemetry: ModuleConfig.TelemetryConfig {
|
||||
get {return _storage._telemetry ?? ModuleConfig.TelemetryConfig()}
|
||||
set {_uniqueStorage()._telemetry = newValue}
|
||||
}
|
||||
/// Returns true if `telemetry` has been explicitly set.
|
||||
var hasTelemetry: Bool {return _storage._telemetry != nil}
|
||||
/// Clears the value of `telemetry`. Subsequent reads from it will return its default value.
|
||||
mutating func clearTelemetry() {_uniqueStorage()._telemetry = nil}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var cannedMessage: ModuleConfig.CannedMessageConfig {
|
||||
get {return _storage._cannedMessage ?? ModuleConfig.CannedMessageConfig()}
|
||||
set {_uniqueStorage()._cannedMessage = newValue}
|
||||
}
|
||||
/// Returns true if `cannedMessage` has been explicitly set.
|
||||
var hasCannedMessage: Bool {return _storage._cannedMessage != nil}
|
||||
/// Clears the value of `cannedMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearCannedMessage() {_uniqueStorage()._cannedMessage = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension ScreenFonts: @unchecked Sendable {}
|
||||
extension DeviceState: @unchecked Sendable {}
|
||||
extension ChannelFile: @unchecked Sendable {}
|
||||
extension OEMStore: @unchecked Sendable {}
|
||||
extension LocalConfig: @unchecked Sendable {}
|
||||
extension LocalModuleConfig: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
|
@ -443,3 +612,227 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "LocalConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "device"),
|
||||
2: .same(proto: "position"),
|
||||
3: .same(proto: "power"),
|
||||
4: .same(proto: "wifi"),
|
||||
5: .same(proto: "display"),
|
||||
6: .same(proto: "lora"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _device: Config.DeviceConfig? = nil
|
||||
var _position: Config.PositionConfig? = nil
|
||||
var _power: Config.PowerConfig? = nil
|
||||
var _wifi: Config.WiFiConfig? = nil
|
||||
var _display: Config.DisplayConfig? = nil
|
||||
var _lora: Config.LoRaConfig? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_device = source._device
|
||||
_position = source._position
|
||||
_power = source._power
|
||||
_wifi = source._wifi
|
||||
_display = source._display
|
||||
_lora = source._lora
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularMessageField(value: &_storage._device) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._position) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &_storage._power) }()
|
||||
case 4: try { try decoder.decodeSingularMessageField(value: &_storage._wifi) }()
|
||||
case 5: try { try decoder.decodeSingularMessageField(value: &_storage._display) }()
|
||||
case 6: try { try decoder.decodeSingularMessageField(value: &_storage._lora) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = _storage._device {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = _storage._position {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = _storage._power {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = _storage._wifi {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try { if let v = _storage._display {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
} }()
|
||||
try { if let v = _storage._lora {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: LocalConfig, rhs: LocalConfig) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._device != rhs_storage._device {return false}
|
||||
if _storage._position != rhs_storage._position {return false}
|
||||
if _storage._power != rhs_storage._power {return false}
|
||||
if _storage._wifi != rhs_storage._wifi {return false}
|
||||
if _storage._display != rhs_storage._display {return false}
|
||||
if _storage._lora != rhs_storage._lora {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "LocalModuleConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "mqtt"),
|
||||
2: .same(proto: "serial"),
|
||||
3: .standard(proto: "external_notification"),
|
||||
4: .standard(proto: "store_forward"),
|
||||
5: .standard(proto: "range_test"),
|
||||
6: .same(proto: "telemetry"),
|
||||
7: .standard(proto: "canned_message"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _mqtt: ModuleConfig.MQTTConfig? = nil
|
||||
var _serial: ModuleConfig.SerialConfig? = nil
|
||||
var _externalNotification: ModuleConfig.ExternalNotificationConfig? = nil
|
||||
var _storeForward: ModuleConfig.StoreForwardConfig? = nil
|
||||
var _rangeTest: ModuleConfig.RangeTestConfig? = nil
|
||||
var _telemetry: ModuleConfig.TelemetryConfig? = nil
|
||||
var _cannedMessage: ModuleConfig.CannedMessageConfig? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_mqtt = source._mqtt
|
||||
_serial = source._serial
|
||||
_externalNotification = source._externalNotification
|
||||
_storeForward = source._storeForward
|
||||
_rangeTest = source._rangeTest
|
||||
_telemetry = source._telemetry
|
||||
_cannedMessage = source._cannedMessage
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularMessageField(value: &_storage._mqtt) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._serial) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &_storage._externalNotification) }()
|
||||
case 4: try { try decoder.decodeSingularMessageField(value: &_storage._storeForward) }()
|
||||
case 5: try { try decoder.decodeSingularMessageField(value: &_storage._rangeTest) }()
|
||||
case 6: try { try decoder.decodeSingularMessageField(value: &_storage._telemetry) }()
|
||||
case 7: try { try decoder.decodeSingularMessageField(value: &_storage._cannedMessage) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = _storage._mqtt {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = _storage._serial {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = _storage._externalNotification {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try { if let v = _storage._storeForward {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try { if let v = _storage._rangeTest {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
} }()
|
||||
try { if let v = _storage._telemetry {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
try { if let v = _storage._cannedMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
} }()
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: LocalModuleConfig, rhs: LocalModuleConfig) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._mqtt != rhs_storage._mqtt {return false}
|
||||
if _storage._serial != rhs_storage._serial {return false}
|
||||
if _storage._externalNotification != rhs_storage._externalNotification {return false}
|
||||
if _storage._storeForward != rhs_storage._storeForward {return false}
|
||||
if _storage._rangeTest != rhs_storage._rangeTest {return false}
|
||||
if _storage._telemetry != rhs_storage._telemetry {return false}
|
||||
if _storage._cannedMessage != rhs_storage._cannedMessage {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1037,27 +1037,9 @@ struct DataMessage {
|
|||
/// Formerly named typ and of type Type
|
||||
var portnum: PortNum = .unknownApp
|
||||
|
||||
var payloadVariant: DataMessage.OneOf_PayloadVariant? = nil
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var payload: Data {
|
||||
get {
|
||||
if case .payload(let v)? = payloadVariant {return v}
|
||||
return Data()
|
||||
}
|
||||
set {payloadVariant = .payload(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var payloadCompressed: Data {
|
||||
get {
|
||||
if case .payloadCompressed(let v)? = payloadVariant {return v}
|
||||
return Data()
|
||||
}
|
||||
set {payloadVariant = .payloadCompressed(newValue)}
|
||||
}
|
||||
var payload: Data = Data()
|
||||
|
||||
///
|
||||
/// Not normally used, but for testing a sender can request that recipient
|
||||
|
|
@ -1106,34 +1088,6 @@ struct DataMessage {
|
|||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
enum OneOf_PayloadVariant: Equatable {
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case payload(Data)
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case payloadCompressed(Data)
|
||||
|
||||
#if !swift(>=4.1)
|
||||
static func ==(lhs: DataMessage.OneOf_PayloadVariant, rhs: DataMessage.OneOf_PayloadVariant) -> Bool {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch (lhs, rhs) {
|
||||
case (.payload, .payload): return {
|
||||
guard case .payload(let l) = lhs, case .payload(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.payloadCompressed, .payloadCompressed): return {
|
||||
guard case .payloadCompressed(let l) = lhs, case .payloadCompressed(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _location: Location? = nil
|
||||
|
|
@ -2142,7 +2096,6 @@ extension Routing: @unchecked Sendable {}
|
|||
extension Routing.OneOf_Variant: @unchecked Sendable {}
|
||||
extension Routing.Error: @unchecked Sendable {}
|
||||
extension DataMessage: @unchecked Sendable {}
|
||||
extension DataMessage.OneOf_PayloadVariant: @unchecked Sendable {}
|
||||
extension Location: @unchecked Sendable {}
|
||||
extension MeshPacket: @unchecked Sendable {}
|
||||
extension MeshPacket.OneOf_PayloadVariant: @unchecked Sendable {}
|
||||
|
|
@ -2684,7 +2637,6 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "portnum"),
|
||||
2: .same(proto: "payload"),
|
||||
10: .standard(proto: "payload_compressed"),
|
||||
3: .standard(proto: "want_response"),
|
||||
4: .same(proto: "dest"),
|
||||
5: .same(proto: "source"),
|
||||
|
|
@ -2701,14 +2653,7 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularEnumField(value: &self.portnum) }()
|
||||
case 2: try {
|
||||
var v: Data?
|
||||
try decoder.decodeSingularBytesField(value: &v)
|
||||
if let v = v {
|
||||
if self.payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .payload(v)
|
||||
}
|
||||
}()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self.payload) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.wantResponse) }()
|
||||
case 4: try { try decoder.decodeSingularFixed32Field(value: &self.dest) }()
|
||||
case 5: try { try decoder.decodeSingularFixed32Field(value: &self.source) }()
|
||||
|
|
@ -2716,14 +2661,6 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
case 7: try { try decoder.decodeSingularFixed32Field(value: &self.replyID) }()
|
||||
case 8: try { try decoder.decodeSingularFixed32Field(value: &self.emoji) }()
|
||||
case 9: try { try decoder.decodeSingularMessageField(value: &self._location) }()
|
||||
case 10: try {
|
||||
var v: Data?
|
||||
try decoder.decodeSingularBytesField(value: &v)
|
||||
if let v = v {
|
||||
if self.payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .payloadCompressed(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -2737,9 +2674,9 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
if self.portnum != .unknownApp {
|
||||
try visitor.visitSingularEnumField(value: self.portnum, fieldNumber: 1)
|
||||
}
|
||||
try { if case .payload(let v)? = self.payloadVariant {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
if !self.payload.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 2)
|
||||
}
|
||||
if self.wantResponse != false {
|
||||
try visitor.visitSingularBoolField(value: self.wantResponse, fieldNumber: 3)
|
||||
}
|
||||
|
|
@ -2761,15 +2698,12 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
try { if let v = self._location {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 9)
|
||||
} }()
|
||||
try { if case .payloadCompressed(let v)? = self.payloadVariant {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 10)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: DataMessage, rhs: DataMessage) -> Bool {
|
||||
if lhs.portnum != rhs.portnum {return false}
|
||||
if lhs.payloadVariant != rhs.payloadVariant {return false}
|
||||
if lhs.payload != rhs.payload {return false}
|
||||
if lhs.wantResponse != rhs.wantResponse {return false}
|
||||
if lhs.dest != rhs.dest {return false}
|
||||
if lhs.source != rhs.source {return false}
|
||||
|
|
|
|||
|
|
@ -253,21 +253,21 @@ struct ModuleConfig {
|
|||
enum Serial_Baud: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
case baudDefault // = 0
|
||||
case baud2400 // = 1
|
||||
case baud4800 // = 2
|
||||
case baud9600 // = 3
|
||||
case baud19200 // = 4
|
||||
case baud38400 // = 5
|
||||
case baud57600 // = 6
|
||||
case baud115200 // = 7
|
||||
case baud230400 // = 8
|
||||
case baud460800 // = 9
|
||||
case baud576000 // = 10
|
||||
case baud921600 // = 11
|
||||
case baud110 // = 12
|
||||
case baud300 // = 13
|
||||
case baud600 // = 14
|
||||
case baud1200 // = 15
|
||||
case baud110 // = 1
|
||||
case baud300 // = 2
|
||||
case baud600 // = 3
|
||||
case baud1200 // = 4
|
||||
case baud2400 // = 5
|
||||
case baud4800 // = 6
|
||||
case baud9600 // = 7
|
||||
case baud19200 // = 8
|
||||
case baud38400 // = 9
|
||||
case baud57600 // = 10
|
||||
case baud115200 // = 11
|
||||
case baud230400 // = 12
|
||||
case baud460800 // = 13
|
||||
case baud576000 // = 14
|
||||
case baud921600 // = 15
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
|
|
@ -277,21 +277,21 @@ struct ModuleConfig {
|
|||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .baudDefault
|
||||
case 1: self = .baud2400
|
||||
case 2: self = .baud4800
|
||||
case 3: self = .baud9600
|
||||
case 4: self = .baud19200
|
||||
case 5: self = .baud38400
|
||||
case 6: self = .baud57600
|
||||
case 7: self = .baud115200
|
||||
case 8: self = .baud230400
|
||||
case 9: self = .baud460800
|
||||
case 10: self = .baud576000
|
||||
case 11: self = .baud921600
|
||||
case 12: self = .baud110
|
||||
case 13: self = .baud300
|
||||
case 14: self = .baud600
|
||||
case 15: self = .baud1200
|
||||
case 1: self = .baud110
|
||||
case 2: self = .baud300
|
||||
case 3: self = .baud600
|
||||
case 4: self = .baud1200
|
||||
case 5: self = .baud2400
|
||||
case 6: self = .baud4800
|
||||
case 7: self = .baud9600
|
||||
case 8: self = .baud19200
|
||||
case 9: self = .baud38400
|
||||
case 10: self = .baud57600
|
||||
case 11: self = .baud115200
|
||||
case 12: self = .baud230400
|
||||
case 13: self = .baud460800
|
||||
case 14: self = .baud576000
|
||||
case 15: self = .baud921600
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -299,21 +299,21 @@ struct ModuleConfig {
|
|||
var rawValue: Int {
|
||||
switch self {
|
||||
case .baudDefault: return 0
|
||||
case .baud2400: return 1
|
||||
case .baud4800: return 2
|
||||
case .baud9600: return 3
|
||||
case .baud19200: return 4
|
||||
case .baud38400: return 5
|
||||
case .baud57600: return 6
|
||||
case .baud115200: return 7
|
||||
case .baud230400: return 8
|
||||
case .baud460800: return 9
|
||||
case .baud576000: return 10
|
||||
case .baud921600: return 11
|
||||
case .baud110: return 12
|
||||
case .baud300: return 13
|
||||
case .baud600: return 14
|
||||
case .baud1200: return 15
|
||||
case .baud110: return 1
|
||||
case .baud300: return 2
|
||||
case .baud600: return 3
|
||||
case .baud1200: return 4
|
||||
case .baud2400: return 5
|
||||
case .baud4800: return 6
|
||||
case .baud9600: return 7
|
||||
case .baud19200: return 8
|
||||
case .baud38400: return 9
|
||||
case .baud57600: return 10
|
||||
case .baud115200: return 11
|
||||
case .baud230400: return 12
|
||||
case .baud460800: return 13
|
||||
case .baud576000: return 14
|
||||
case .baud921600: return 15
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -643,6 +643,10 @@ extension ModuleConfig.SerialConfig.Serial_Baud: CaseIterable {
|
|||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [ModuleConfig.SerialConfig.Serial_Baud] = [
|
||||
.baudDefault,
|
||||
.baud110,
|
||||
.baud300,
|
||||
.baud600,
|
||||
.baud1200,
|
||||
.baud2400,
|
||||
.baud4800,
|
||||
.baud9600,
|
||||
|
|
@ -654,10 +658,6 @@ extension ModuleConfig.SerialConfig.Serial_Baud: CaseIterable {
|
|||
.baud460800,
|
||||
.baud576000,
|
||||
.baud921600,
|
||||
.baud110,
|
||||
.baud300,
|
||||
.baud600,
|
||||
.baud1200,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -990,21 +990,21 @@ extension ModuleConfig.SerialConfig: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
extension ModuleConfig.SerialConfig.Serial_Baud: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "BAUD_Default"),
|
||||
1: .same(proto: "BAUD_2400"),
|
||||
2: .same(proto: "BAUD_4800"),
|
||||
3: .same(proto: "BAUD_9600"),
|
||||
4: .same(proto: "BAUD_19200"),
|
||||
5: .same(proto: "BAUD_38400"),
|
||||
6: .same(proto: "BAUD_57600"),
|
||||
7: .same(proto: "BAUD_115200"),
|
||||
8: .same(proto: "BAUD_230400"),
|
||||
9: .same(proto: "BAUD_460800"),
|
||||
10: .same(proto: "BAUD_576000"),
|
||||
11: .same(proto: "BAUD_921600"),
|
||||
12: .same(proto: "BAUD_110"),
|
||||
13: .same(proto: "BAUD_300"),
|
||||
14: .same(proto: "BAUD_600"),
|
||||
15: .same(proto: "BAUD_1200"),
|
||||
1: .same(proto: "BAUD_110"),
|
||||
2: .same(proto: "BAUD_300"),
|
||||
3: .same(proto: "BAUD_600"),
|
||||
4: .same(proto: "BAUD_1200"),
|
||||
5: .same(proto: "BAUD_2400"),
|
||||
6: .same(proto: "BAUD_4800"),
|
||||
7: .same(proto: "BAUD_9600"),
|
||||
8: .same(proto: "BAUD_19200"),
|
||||
9: .same(proto: "BAUD_38400"),
|
||||
10: .same(proto: "BAUD_57600"),
|
||||
11: .same(proto: "BAUD_115200"),
|
||||
12: .same(proto: "BAUD_230400"),
|
||||
13: .same(proto: "BAUD_460800"),
|
||||
14: .same(proto: "BAUD_576000"),
|
||||
15: .same(proto: "BAUD_921600"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
/// Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message
|
||||
case adminApp // = 6
|
||||
|
||||
///
|
||||
/// Compressed TEXT_MESSAGE payloads.
|
||||
case textMessageCompressedApp // = 7
|
||||
|
||||
///
|
||||
/// Provides a 'ping' service that replies to any packet it receives.
|
||||
/// Also serves as a small example module.
|
||||
|
|
@ -110,10 +114,6 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
/// Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
|
||||
case zpsApp // = 68
|
||||
|
||||
///
|
||||
/// Compressed payloads.
|
||||
case compressionApp // = 69
|
||||
|
||||
///
|
||||
/// Private applications should use portnums >= 256.
|
||||
/// To simplify initial development and testing you can use "PRIVATE_APP"
|
||||
|
|
@ -142,6 +142,7 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
case 4: self = .nodeinfoApp
|
||||
case 5: self = .routingApp
|
||||
case 6: self = .adminApp
|
||||
case 7: self = .textMessageCompressedApp
|
||||
case 32: self = .replyApp
|
||||
case 33: self = .ipTunnelApp
|
||||
case 64: self = .serialApp
|
||||
|
|
@ -149,7 +150,6 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
case 66: self = .rangeTestApp
|
||||
case 67: self = .telemetryApp
|
||||
case 68: self = .zpsApp
|
||||
case 69: self = .compressionApp
|
||||
case 256: self = .privateApp
|
||||
case 257: self = .atakForwarder
|
||||
case 511: self = .max
|
||||
|
|
@ -166,6 +166,7 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
case .nodeinfoApp: return 4
|
||||
case .routingApp: return 5
|
||||
case .adminApp: return 6
|
||||
case .textMessageCompressedApp: return 7
|
||||
case .replyApp: return 32
|
||||
case .ipTunnelApp: return 33
|
||||
case .serialApp: return 64
|
||||
|
|
@ -173,7 +174,6 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
case .rangeTestApp: return 66
|
||||
case .telemetryApp: return 67
|
||||
case .zpsApp: return 68
|
||||
case .compressionApp: return 69
|
||||
case .privateApp: return 256
|
||||
case .atakForwarder: return 257
|
||||
case .max: return 511
|
||||
|
|
@ -195,6 +195,7 @@ extension PortNum: CaseIterable {
|
|||
.nodeinfoApp,
|
||||
.routingApp,
|
||||
.adminApp,
|
||||
.textMessageCompressedApp,
|
||||
.replyApp,
|
||||
.ipTunnelApp,
|
||||
.serialApp,
|
||||
|
|
@ -202,7 +203,6 @@ extension PortNum: CaseIterable {
|
|||
.rangeTestApp,
|
||||
.telemetryApp,
|
||||
.zpsApp,
|
||||
.compressionApp,
|
||||
.privateApp,
|
||||
.atakForwarder,
|
||||
.max,
|
||||
|
|
@ -226,6 +226,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
|
|||
4: .same(proto: "NODEINFO_APP"),
|
||||
5: .same(proto: "ROUTING_APP"),
|
||||
6: .same(proto: "ADMIN_APP"),
|
||||
7: .same(proto: "TEXT_MESSAGE_COMPRESSED_APP"),
|
||||
32: .same(proto: "REPLY_APP"),
|
||||
33: .same(proto: "IP_TUNNEL_APP"),
|
||||
64: .same(proto: "SERIAL_APP"),
|
||||
|
|
@ -233,7 +234,6 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
|
|||
66: .same(proto: "RANGE_TEST_APP"),
|
||||
67: .same(proto: "TELEMETRY_APP"),
|
||||
68: .same(proto: "ZPS_APP"),
|
||||
69: .same(proto: "COMPRESSION_APP"),
|
||||
256: .same(proto: "PRIVATE_APP"),
|
||||
257: .same(proto: "ATAK_FORWARDER"),
|
||||
511: .same(proto: "MAX"),
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -265,8 +265,8 @@ struct Connect: View {
|
|||
ConnectedDevice(
|
||||
bluetoothOn: self.bleManager.isSwitchedOn,
|
||||
deviceConnected: self.bleManager.connectedPeripheral != nil,
|
||||
name: (bleManager.connectedPeripheral != nil) ? self.bleManager.connectedPeripheral.shortName :
|
||||
"???")
|
||||
name: (bleManager.connectedPeripheral != nil) ? self.bleManager.connectedPeripheral.lastFourCode :
|
||||
"????")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import SwiftUI
|
|||
//
|
||||
struct LastHeardText: View {
|
||||
var lastHeard: Date?
|
||||
|
||||
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -16,7 +17,7 @@ struct LastHeardText: View {
|
|||
|
||||
} else {
|
||||
|
||||
Text("Last Heard: Unknown Age")
|
||||
Text("Unknown Age")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ struct UserMessageList: View {
|
|||
ConnectedDevice(
|
||||
bluetoothOn: bleManager.isSwitchedOn,
|
||||
deviceConnected: bleManager.connectedPeripheral != nil,
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "???")
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode : "????")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,16 +133,18 @@ struct NodeDetail: View {
|
|||
|
||||
BatteryIcon(batteryLevel: mostRecent.batteryLevel, font: .title, color: .accentColor)
|
||||
.padding(.bottom)
|
||||
Text(String(mostRecent.batteryLevel) + "%")
|
||||
.font(.title3)
|
||||
.foregroundColor(.gray)
|
||||
.fixedSize()
|
||||
|
||||
if mostRecent.batteryLevel > 0 {
|
||||
Text(String(mostRecent.batteryLevel) + "%")
|
||||
.font(.title3)
|
||||
.foregroundColor(.gray)
|
||||
.fixedSize()
|
||||
}
|
||||
|
||||
Text(String(format: "%.2f", mostRecent.voltage) + " V")
|
||||
.font(.title3)
|
||||
.foregroundColor(.gray)
|
||||
.fixedSize()
|
||||
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
}
|
||||
|
|
@ -281,7 +283,7 @@ struct NodeDetail: View {
|
|||
ConnectedDevice(
|
||||
bluetoothOn: bleManager.isSwitchedOn,
|
||||
deviceConnected: bleManager.connectedPeripheral != nil,
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "???")
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode : "????")
|
||||
}
|
||||
)
|
||||
.onAppear(perform: {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ struct NodeList: View {
|
|||
|
||||
HStack(alignment: .bottom) {
|
||||
|
||||
Image(systemName: "repeat.circle.fill").font(.title3)
|
||||
Image(systemName: "repeat.circle.fill").font(.title2)
|
||||
.foregroundColor(.accentColor).symbolRenderingMode(.hierarchical)
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
||||
|
|
@ -83,7 +83,8 @@ struct NodeList: View {
|
|||
|
||||
HStack(alignment: .bottom) {
|
||||
|
||||
Image(systemName: "clock.badge.checkmark.fill").font(.title3).foregroundColor(.accentColor).symbolRenderingMode(.hierarchical)
|
||||
Image(systemName: "clock.badge.checkmark.fill").font(.title3)
|
||||
.foregroundColor(.accentColor).symbolRenderingMode(.hierarchical)
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
||||
LastHeardText(lastHeard: node.lastHeard).font(.subheadline).foregroundColor(.gray)
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ struct NodeMap: View {
|
|||
ConnectedDevice(
|
||||
bluetoothOn: bleManager.isSwitchedOn,
|
||||
deviceConnected: bleManager.connectedPeripheral != nil,
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName :
|
||||
"???")
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode :
|
||||
"????")
|
||||
})
|
||||
.onAppear(perform: {
|
||||
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ struct AppSettings: View {
|
|||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "???")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ struct ShareChannel: View {
|
|||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "???")
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.lastFourCode : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fi
|
|||
pdir=$(realpath "../Meshtastic-protobufs")
|
||||
sdir=$(realpath "./MeshtasticClient/Protobufs")
|
||||
echo "pdir:$pdir sdir:$sdir"
|
||||
pfiles="admin.proto apponly.proto cannedmessages.proto channel.proto config.proto deviceonly.proto mesh.proto module_config.proto mqtt.proto portnums.proto radioconfig.proto remote_hardware.proto storeforward.proto telemetry.proto"
|
||||
pfiles="admin.proto apponly.proto cannedmessages.proto channel.proto config.proto deviceonly.proto mesh.proto module_config.proto mqtt.proto portnums.proto remote_hardware.proto storeforward.proto telemetry.proto"
|
||||
for pf in $pfiles
|
||||
do
|
||||
echo "Generating $pf..."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue