diff --git a/Meshtastic Client.xcodeproj/project.pbxproj b/Meshtastic Client.xcodeproj/project.pbxproj index 6717fae4..3b649743 100644 --- a/Meshtastic Client.xcodeproj/project.pbxproj +++ b/Meshtastic Client.xcodeproj/project.pbxproj @@ -3,12 +3,23 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5226EB1DF10058C060 /* BLEManager.swift */; }; - DDAF8C5526EBA0530058C060 /* Bluetooth.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5426EBA0530058C060 /* Bluetooth.swift */; }; + DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */; }; + DDAF8C5B26ED08D30058C060 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = DDAF8C5A26ED08D30058C060 /* SwiftProtobuf */; }; + 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 */; }; + DDAF8C6726ED0C8C0058C060 /* remote_hardware.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6626ED0C8C0058C060 /* remote_hardware.pb.swift */; }; + DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */; }; + DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6A26ED0DD80058C060 /* environmental_measurement.pb.swift */; }; + DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6D26ED19040058C060 /* Extensions.swift */; }; + DDAF8C7026ED1DD20058C060 /* Device2.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6F26ED1DD20058C060 /* Device2.swift */; }; DDC2E15826CE248E0042C5E4 /* MeshtasticClientApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E15726CE248E0042C5E4 /* MeshtasticClientApp.swift */; }; DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */; }; DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; }; @@ -48,7 +59,18 @@ /* Begin PBXFileReference section */ DDAF8C5226EB1DF10058C060 /* BLEManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManager.swift; sourceTree = ""; }; - DDAF8C5426EBA0530058C060 /* Bluetooth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bluetooth.swift; sourceTree = ""; }; + DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mesh.pb.swift; sourceTree = ""; }; + DDAF8C5C26ED09490058C060 /* portnums.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = portnums.pb.swift; sourceTree = ""; }; + DDAF8C5E26ED09B50058C060 /* radioconfig.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = radioconfig.pb.swift; sourceTree = ""; }; + DDAF8C6026ED0A230058C060 /* mqtt.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = mqtt.pb.swift; sourceTree = ""; }; + DDAF8C6126ED0A230058C060 /* admin.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = admin.pb.swift; sourceTree = ""; }; + DDAF8C6426ED0A490058C060 /* channel.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = channel.pb.swift; sourceTree = ""; }; + DDAF8C6626ED0C8C0058C060 /* remote_hardware.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = remote_hardware.pb.swift; sourceTree = ""; }; + DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = deviceonly.pb.swift; sourceTree = ""; }; + DDAF8C6A26ED0DD80058C060 /* environmental_measurement.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = environmental_measurement.pb.swift; sourceTree = ""; }; + DDAF8C6D26ED19040058C060 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + DDAF8C6F26ED1DD20058C060 /* Device2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Device2.swift; sourceTree = ""; }; + DDAF8C7126ED2AD80058C060 /* nodeInfo.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = nodeInfo.json; sourceTree = ""; }; DDC2E15426CE248E0042C5E4 /* MeshtasticClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MeshtasticClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; DDC2E15726CE248E0042C5E4 /* MeshtasticClientApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticClientApp.swift; sourceTree = ""; }; DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -80,6 +102,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DDAF8C5B26ED08D30058C060 /* SwiftProtobuf in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -100,6 +123,22 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + DDAF8C5626ED07740058C060 /* Protobufs */ = { + isa = PBXGroup; + children = ( + DDAF8C5E26ED09B50058C060 /* radioconfig.pb.swift */, + DDAF8C6426ED0A490058C060 /* channel.pb.swift */, + DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */, + DDAF8C5C26ED09490058C060 /* portnums.pb.swift */, + DDAF8C6626ED0C8C0058C060 /* remote_hardware.pb.swift */, + DDAF8C6A26ED0DD80058C060 /* environmental_measurement.pb.swift */, + DDAF8C6126ED0A230058C060 /* admin.pb.swift */, + DDAF8C6026ED0A230058C060 /* mqtt.pb.swift */, + DDAF8C5726ED07FD0058C060 /* mesh.pb.swift */, + ); + path = Protobufs; + sourceTree = ""; + }; DDC2E14B26CE248E0042C5E4 = { isa = PBXGroup; children = ( @@ -123,6 +162,7 @@ DDC2E15626CE248E0042C5E4 /* MeshtasticClient */ = { isa = PBXGroup; children = ( + DDAF8C5626ED07740058C060 /* Protobufs */, DDC2E1A526CEB32B0042C5E4 /* Helpers */, DDC2E18726CE24E40042C5E4 /* Views */, DDC2E18826CE24EE0042C5E4 /* Model */, @@ -177,6 +217,7 @@ children = ( DDC2E19C26CE27580042C5E4 /* ModelData.swift */, DDC2E19E26CE27630042C5E4 /* Device.swift */, + DDAF8C6F26ED1DD20058C060 /* Device2.swift */, ); path = Model; sourceTree = ""; @@ -186,6 +227,7 @@ children = ( DDC2E18A26CE25690042C5E4 /* deviceData.json */, DDC2E1AA26DD89EC0042C5E4 /* packets.json */, + DDAF8C7126ED2AD80058C060 /* nodeInfo.json */, ); path = Resources; sourceTree = ""; @@ -206,7 +248,6 @@ DDC2E19626CE26840042C5E4 /* DeviceRow.swift */, DDC2E19826CE26940042C5E4 /* DeviceMap.swift */, DDC2E1A326CE2F940042C5E4 /* DeviceBLE.swift */, - DDAF8C5426EBA0530058C060 /* Bluetooth.swift */, ); path = Devices; sourceTree = ""; @@ -215,7 +256,6 @@ isa = PBXGroup; children = ( DDC2E19A26CE27150042C5E4 /* CircleImage.swift */, - DDAF8C5226EB1DF10058C060 /* BLEManager.swift */, ); path = Helpers; sourceTree = ""; @@ -223,7 +263,9 @@ DDC2E1A526CEB32B0042C5E4 /* Helpers */ = { isa = PBXGroup; children = ( + DDAF8C5226EB1DF10058C060 /* BLEManager.swift */, DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */, + DDAF8C6D26ED19040058C060 /* Extensions.swift */, ); path = Helpers; sourceTree = ""; @@ -244,6 +286,9 @@ dependencies = ( ); name = MeshtasticClient; + packageProductDependencies = ( + DDAF8C5A26ED08D30058C060 /* SwiftProtobuf */, + ); productName = MeshtasticClient; productReference = DDC2E15426CE248E0042C5E4 /* MeshtasticClient.app */; productType = "com.apple.product-type.application"; @@ -315,6 +360,9 @@ Base, ); mainGroup = DDC2E14B26CE248E0042C5E4; + packageReferences = ( + DDAF8C5926ED08D30058C060 /* XCRemoteSwiftPackageReference "swift-protobuf" */, + ); productRefGroup = DDC2E15526CE248E0042C5E4 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -359,19 +407,29 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */, DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */, + DDAF8C7026ED1DD20058C060 /* Device2.swift in Sources */, DDC2E19F26CE27630042C5E4 /* Device.swift in Sources */, DDC2E19926CE26940042C5E4 /* DeviceMap.swift in Sources */, DDC2E19526CE26760042C5E4 /* DeviceDetail.swift in Sources */, + DDAF8C5F26ED09B50058C060 /* radioconfig.pb.swift in Sources */, DDC2E19726CE26840042C5E4 /* DeviceRow.swift in Sources */, DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */, - DDAF8C5526EBA0530058C060 /* Bluetooth.swift in Sources */, DDC2E19126CE26290042C5E4 /* Messages.swift in Sources */, + DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */, DDC2E19D26CE27580042C5E4 /* ModelData.swift in Sources */, + DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */, + DDAF8C6226ED0A230058C060 /* mqtt.pb.swift in Sources */, + DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */, DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */, + DDAF8C6326ED0A230058C060 /* admin.pb.swift in Sources */, + DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */, DDC2E19326CE266B0042C5E4 /* DeviceHome.swift in Sources */, DDC2E19B26CE27150042C5E4 /* CircleImage.swift in Sources */, + DDAF8C6726ED0C8C0058C060 /* remote_hardware.pb.swift in Sources */, DDC2E1A426CE2F940042C5E4 /* DeviceBLE.swift in Sources */, + DDAF8C6526ED0A490058C060 /* channel.pb.swift in Sources */, DDC2E15826CE248E0042C5E4 /* MeshtasticClientApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -692,6 +750,25 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + DDAF8C5926ED08D30058C060 /* XCRemoteSwiftPackageReference "swift-protobuf" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-protobuf.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.17.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + DDAF8C5A26ED08D30058C060 /* SwiftProtobuf */ = { + isa = XCSwiftPackageProductDependency; + package = DDAF8C5926ED08D30058C060 /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = SwiftProtobuf; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = DDC2E14C26CE248E0042C5E4 /* Project object */; } diff --git a/Meshtastic Client.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Meshtastic Client.xcodeproj/project.xcworkspace/contents.xcworkspacedata index bb6f0e78..919434a6 100644 --- a/Meshtastic Client.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Meshtastic Client.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/MeshtasticClient/Views/Helpers/BLEManager.swift b/MeshtasticClient/Helpers/BLEManager.swift similarity index 74% rename from MeshtasticClient/Views/Helpers/BLEManager.swift rename to MeshtasticClient/Helpers/BLEManager.swift index d6eaa58e..a6931d7a 100644 --- a/MeshtasticClient/Views/Helpers/BLEManager.swift +++ b/MeshtasticClient/Helpers/BLEManager.swift @@ -63,10 +63,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph // Start Scanning print("Start Scanning") centralManager.scanForPeripherals(withServices: [meshtasticServiceCBUUID]) - // scanningLabel.text = "Scanning..." } - //Timer.scheduledTimer(withTimeInterval: 15, repeats: false) {_ in - // self.stopScanning() - //} } //--------------------------------------------------------------------------------------- @@ -74,7 +70,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph //--------------------------------------------------------------------------------------- func stopScanning() { print("Stop Scanning") - centralManager.stopScan() + self.centralManager.stopScan() } //--------------------------------------------------------------------------------------- @@ -82,7 +78,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph //--------------------------------------------------------------------------------------- func connectToDevice(id: String) { connectedPeripheral = peripheralArray.filter({ $0.identifier.uuidString == id }).first - centralManager?.connect(connectedPeripheral!) + self.centralManager?.connect(connectedPeripheral!) } //--------------------------------------------------------------------------------------- @@ -90,7 +86,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph //--------------------------------------------------------------------------------------- func disconnectDevice(){ if connectedPeripheral != nil { - centralManager?.cancelPeripheralConnection(connectedPeripheral!) + self.centralManager?.cancelPeripheralConnection(connectedPeripheral!) } } @@ -169,7 +165,8 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph //--------------------------------------------------------------------------------------- // Discover Characteristics Event //--------------------------------------------------------------------------------------- - func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { + func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) + { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { @@ -179,10 +176,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph case TORADIO_UUID: print("TORADIO characteristic OK") TORADIO_characteristic = characteristic - // var toRadio: ToRadio = ToRadio() - // toRadio.wantConfigID = 32168 - // let binaryData: Data = try! toRadio.serializedData() - // peripheral.writeValue(binaryData, for: characteristic, type: .withResponse) + var toRadio: ToRadio = ToRadio() + toRadio.wantConfigID = 32168 + let binaryData: Data = try! toRadio.serializedData() + peripheral.writeValue(binaryData, for: characteristic, type: .withResponse) break case FROMRADIO_UUID: @@ -205,15 +202,68 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph } //--------------------------------------------------------------------------------------- - // Update Characteristic Event + // Data Read / Update Characteristic Event //--------------------------------------------------------------------------------------- - func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, - error: Error?) { - switch characteristic.uuid { - case FROMRADIO_UUID: - print(characteristic.value ?? "no value") - default: - print("Unhandled Characteristic UUID: \(characteristic.uuid)") - } + func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) + { + switch characteristic.uuid + { + case FROMNUM_UUID: + peripheral.readValue(for: FROMRADIO_characteristic) + + case FROMRADIO_UUID: + if (characteristic.value == nil || characteristic.value!.isEmpty) + { + return + } + //print(characteristic.value ?? "no value") + //let byteArray = [UInt8](characteristic.value!) + //print(characteristic.value?.hexDescription ?? "no value") + var decodedInfo = FromRadio() + + decodedInfo = try! FromRadio(serializedData: characteristic.value!) + //print(decodedInfo.myInfo.myNodeNum) + + if decodedInfo.myInfo.myNodeNum != 0 + { + print("Save a myInfo") + do { + print(try decodedInfo.myInfo.jsonString()) + } catch { + fatalError("Failed to decode json") + } + } + + if decodedInfo.nodeInfo.num != 0 + { + print("Save a nodeInfo") + do { + print(try decodedInfo.nodeInfo.jsonString()) + } catch { + fatalError("Failed to decode json") + } + } + + if decodedInfo.packet.from != 0 + { + print("Save a packet") + do { + print(try decodedInfo.packet.jsonString()) + } catch { + fatalError("Failed to decode json") + } + } + + if decodedInfo.configCompleteID != 0 { + print(decodedInfo) + } + + default: + print("Unhandled Characteristic UUID: \(characteristic.uuid)") + } + + peripheral.readValue(for: FROMRADIO_characteristic) } } + + diff --git a/MeshtasticClient/Helpers/Extensions.swift b/MeshtasticClient/Helpers/Extensions.swift new file mode 100644 index 00000000..5e9b5960 --- /dev/null +++ b/MeshtasticClient/Helpers/Extensions.swift @@ -0,0 +1,46 @@ +import Foundation + +extension Data +{ + var hexDescription: String + { + return reduce("") {$0 + String(format: "%02x", $1)} + } +} + + +extension String +{ + + /// Create `Data` from hexadecimal string representation + /// + /// This creates a `Data` object from hex string. Note, if the string has any spaces or non-hex characters (e.g. starts with '<' and with a '>'), those are ignored and only hex characters are processed. + /// + /// - returns: Data represented by this hexadecimal string. + + var hexadecimal: Data? + { + var data = Data(capacity: count / 2) + + let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive) + regex.enumerateMatches(in: self, range: NSRange(startIndex..., in: self)) { match, _, _ in + let byteString = (self as NSString).substring(with: match!.range) + let num = UInt8(byteString, radix: 16)! + data.append(num) + } + + guard data.count > 0 else { return nil } + + return data + } + +} + + +extension Date +{ + static var currentTimeStamp: Int64 + { + return Int64(Date().timeIntervalSince1970 * 1000) + } +} diff --git a/MeshtasticClient/Helpers/LocationHelper.swift b/MeshtasticClient/Helpers/LocationHelper.swift index 1e7e83fb..1726011e 100644 --- a/MeshtasticClient/Helpers/LocationHelper.swift +++ b/MeshtasticClient/Helpers/LocationHelper.swift @@ -1,10 +1,3 @@ -// -// LocationHelper.swift -// RChat -// -// Created by Andrew Morgan on 24/11/2020. -// - import CoreLocation struct MyAnnotationItem: Identifiable { diff --git a/MeshtasticClient/Model/Device2.swift b/MeshtasticClient/Model/Device2.swift new file mode 100644 index 00000000..6980fab6 --- /dev/null +++ b/MeshtasticClient/Model/Device2.swift @@ -0,0 +1,45 @@ +/* +See LICENSE folder for this app’s licensing information. + +Abstract: +A representation of a single device. +*/ + +import Foundation +import SwiftUI +import CoreLocation + +struct Device2: Hashable, Codable, Identifiable { + + var id: String + var num: Int32 + + struct MyInfo: Hashable, Codable { + + var hasGps: Bool + var numBands: Int32 + var maxChannels: Int32 + var firmwareVersion: String + var rebootCount: Int32 + var messageTimeoutMsec: Int32 + var minAppVersion: Int32 + } + + + struct User: Hashable, Codable { + var id: String + var longName: String + var shortName: String + var macaddr: String + var hwModel: String + } + + struct Position: Hashable, Codable { + var latitude: Int32 + var longitude: Int32 + var altitude: Int32 + var batteryLevel: Int + } + var lastHeard: Int32 + +} diff --git a/MeshtasticClient/Protobufs/admin.pb.swift b/MeshtasticClient/Protobufs/admin.pb.swift new file mode 100644 index 00000000..8c864002 --- /dev/null +++ b/MeshtasticClient/Protobufs/admin.pb.swift @@ -0,0 +1,447 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: admin.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// This message is handled by the Admin plugin and is responsible for all settings/channel read/write operations. +/// This message is used to do settings operations to both remote AND local nodes. +/// (Prior to 1.2 these operations were done via special ToRadio operations) +struct AdminMessage { + // 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. + + var variant: AdminMessage.OneOf_Variant? = nil + + /// + /// set the radio provisioning for this node + var setRadio: RadioConfig { + get { + if case .setRadio(let v)? = variant {return v} + return RadioConfig() + } + set {variant = .setRadio(newValue)} + } + + /// + /// Set the owner for this node + var setOwner: User { + get { + if case .setOwner(let v)? = variant {return v} + return User() + } + set {variant = .setOwner(newValue)} + } + + /// + /// Set channels (using the new API). + /// A special channel is the "primary channel". + /// The other records are secondary channels. + /// Note: only one channel can be marked as primary. + /// If the client sets a particular channel to be primary, the previous channel will be set to SECONDARY automatically. + var setChannel: Channel { + get { + if case .setChannel(let v)? = variant {return v} + return Channel() + } + set {variant = .setChannel(newValue)} + } + + /// + /// Send the current RadioConfig in the response for this message. + var getRadioRequest: Bool { + get { + if case .getRadioRequest(let v)? = variant {return v} + return false + } + set {variant = .getRadioRequest(newValue)} + } + + var getRadioResponse: RadioConfig { + get { + if case .getRadioResponse(let v)? = variant {return v} + return RadioConfig() + } + set {variant = .getRadioResponse(newValue)} + } + + /// + /// Send the specified channel in the response for this message + /// NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present) + var getChannelRequest: UInt32 { + get { + if case .getChannelRequest(let v)? = variant {return v} + return 0 + } + set {variant = .getChannelRequest(newValue)} + } + + var getChannelResponse: Channel { + get { + if case .getChannelResponse(let v)? = variant {return v} + return Channel() + } + set {variant = .getChannelResponse(newValue)} + } + + /// + /// Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again. + /// Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes. + /// If you fail to do so, the radio will assume loss of comms and revert your changes. + /// These messages are optional when changing the local node. + var confirmSetChannel: Bool { + get { + if case .confirmSetChannel(let v)? = variant {return v} + return false + } + set {variant = .confirmSetChannel(newValue)} + } + + var confirmSetRadio: Bool { + get { + if case .confirmSetRadio(let v)? = variant {return v} + return false + } + set {variant = .confirmSetRadio(newValue)} + } + + /// + /// This message is only supported for the simulator porduino build. + /// If received the simulator will exit successfully. + var exitSimulator: Bool { + get { + if case .exitSimulator(let v)? = variant {return v} + return false + } + set {variant = .exitSimulator(newValue)} + } + + /// + /// Tell the node to reboot in this many seconds (or <0 to cancel reboot) + var rebootSeconds: Int32 { + get { + if case .rebootSeconds(let v)? = variant {return v} + return 0 + } + set {variant = .rebootSeconds(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum OneOf_Variant: Equatable { + /// + /// set the radio provisioning for this node + case setRadio(RadioConfig) + /// + /// Set the owner for this node + case setOwner(User) + /// + /// Set channels (using the new API). + /// A special channel is the "primary channel". + /// The other records are secondary channels. + /// Note: only one channel can be marked as primary. + /// If the client sets a particular channel to be primary, the previous channel will be set to SECONDARY automatically. + case setChannel(Channel) + /// + /// Send the current RadioConfig in the response for this message. + case getRadioRequest(Bool) + case getRadioResponse(RadioConfig) + /// + /// Send the specified channel in the response for this message + /// NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present) + case getChannelRequest(UInt32) + case getChannelResponse(Channel) + /// + /// Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again. + /// Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes. + /// If you fail to do so, the radio will assume loss of comms and revert your changes. + /// These messages are optional when changing the local node. + case confirmSetChannel(Bool) + case confirmSetRadio(Bool) + /// + /// This message is only supported for the simulator porduino build. + /// If received the simulator will exit successfully. + case exitSimulator(Bool) + /// + /// Tell the node to reboot in this many seconds (or <0 to cancel reboot) + case rebootSeconds(Int32) + + #if !swift(>=4.1) + static func ==(lhs: AdminMessage.OneOf_Variant, rhs: AdminMessage.OneOf_Variant) -> 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 (.setRadio, .setRadio): return { + guard case .setRadio(let l) = lhs, case .setRadio(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setOwner, .setOwner): return { + guard case .setOwner(let l) = lhs, case .setOwner(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setChannel, .setChannel): return { + guard case .setChannel(let l) = lhs, case .setChannel(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getRadioRequest, .getRadioRequest): return { + guard case .getRadioRequest(let l) = lhs, case .getRadioRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getRadioResponse, .getRadioResponse): return { + guard case .getRadioResponse(let l) = lhs, case .getRadioResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getChannelRequest, .getChannelRequest): return { + guard case .getChannelRequest(let l) = lhs, case .getChannelRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getChannelResponse, .getChannelResponse): return { + guard case .getChannelResponse(let l) = lhs, case .getChannelResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.confirmSetChannel, .confirmSetChannel): return { + guard case .confirmSetChannel(let l) = lhs, case .confirmSetChannel(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.confirmSetRadio, .confirmSetRadio): return { + guard case .confirmSetRadio(let l) = lhs, case .confirmSetRadio(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.exitSimulator, .exitSimulator): return { + guard case .exitSimulator(let l) = lhs, case .exitSimulator(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rebootSeconds, .rebootSeconds): return { + guard case .rebootSeconds(let l) = lhs, case .rebootSeconds(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "AdminMessage" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "set_radio"), + 2: .standard(proto: "set_owner"), + 3: .standard(proto: "set_channel"), + 4: .standard(proto: "get_radio_request"), + 5: .standard(proto: "get_radio_response"), + 6: .standard(proto: "get_channel_request"), + 7: .standard(proto: "get_channel_response"), + 32: .standard(proto: "confirm_set_channel"), + 33: .standard(proto: "confirm_set_radio"), + 34: .standard(proto: "exit_simulator"), + 35: .standard(proto: "reboot_seconds"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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 { + var v: RadioConfig? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .setRadio(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .setRadio(v) + } + }() + case 2: try { + var v: User? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .setOwner(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .setOwner(v) + } + }() + case 3: try { + var v: Channel? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .setChannel(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .setChannel(v) + } + }() + case 4: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .getRadioRequest(v) + } + }() + case 5: try { + var v: RadioConfig? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .getRadioResponse(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .getRadioResponse(v) + } + }() + case 6: try { + var v: UInt32? + try decoder.decodeSingularUInt32Field(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .getChannelRequest(v) + } + }() + case 7: try { + var v: Channel? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .getChannelResponse(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .getChannelResponse(v) + } + }() + case 32: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .confirmSetChannel(v) + } + }() + case 33: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .confirmSetRadio(v) + } + }() + case 34: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .exitSimulator(v) + } + }() + case 35: try { + var v: Int32? + try decoder.decodeSingularInt32Field(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .rebootSeconds(v) + } + }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // 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 self.variant { + case .setRadio?: try { + guard case .setRadio(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + }() + case .setOwner?: try { + guard case .setOwner(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + }() + case .setChannel?: try { + guard case .setChannel(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + }() + case .getRadioRequest?: try { + guard case .getRadioRequest(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 4) + }() + case .getRadioResponse?: try { + guard case .getRadioResponse(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) + }() + case .getChannelRequest?: try { + guard case .getChannelRequest(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 6) + }() + case .getChannelResponse?: try { + guard case .getChannelResponse(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + }() + case .confirmSetChannel?: try { + guard case .confirmSetChannel(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 32) + }() + case .confirmSetRadio?: try { + guard case .confirmSetRadio(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 33) + }() + case .exitSimulator?: try { + guard case .exitSimulator(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 34) + }() + case .rebootSeconds?: try { + guard case .rebootSeconds(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularInt32Field(value: v, fieldNumber: 35) + }() + case nil: break + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: AdminMessage, rhs: AdminMessage) -> Bool { + if lhs.variant != rhs.variant {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticClient/Protobufs/channel.pb.swift b/MeshtasticClient/Protobufs/channel.pb.swift new file mode 100644 index 00000000..be4ded9b --- /dev/null +++ b/MeshtasticClient/Protobufs/channel.pb.swift @@ -0,0 +1,491 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: channel.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +/// +/// Meshtastic protobufs +/// +/// For more information on protobufs (and tools to use them with the language of your choice) see +/// https://developers.google.com/protocol-buffers/docs/proto3 +/// +/// We are not placing any of these defs inside a package, because if you do the +/// resulting nanopb version is super verbose package mesh. +/// +/// Protobuf build instructions: +/// +/// To build java classes for reading writing: +/// protoc -I=. --java_out /tmp mesh.proto +/// +/// To generate Nanopb c code: +/// /home/kevinh/packages/nanopb-0.4.0-linux-x86/generator-bin/protoc --nanopb_out=/tmp -I=app/src/main/proto mesh.proto +/// +/// Nanopb binaries available here: https://jpa.kapsi.fi/nanopb/download/ use nanopb 0.4.0 + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// Full settings (center freq, spread factor, pre-shared secret key etc...) +/// needed to configure a radio for speaking on a particular channel This +/// information can be encoded as a QRcode/url so that other users can configure +/// their radio to join the same channel. +/// A note about how channel names are shown to users: channelname-Xy +/// poundsymbol is a prefix used to indicate this is a channel name (idea from @professr). +/// Where X is a letter from A-Z (base 26) representing a hash of the PSK for this +/// channel - so that if the user changes anything about the channel (which does +/// force a new PSK) this letter will also change. Thus preventing user confusion if +/// two friends try to type in a channel name of "BobsChan" and then can't talk +/// because their PSKs will be different. +/// The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26" +/// This also allows the option of someday if people have the PSK off (zero), the +/// users COULD type in a channel name and be able to talk. +/// Y is a lower case letter from a-z that represents the channel 'speed' settings +/// (for some future definition of speed) +/// +/// FIXME: Add description of multi-channel support and how primary vs secondary channels are used. +/// FIXME: explain how apps use channels for security. +/// explain how remote settings and remote gpio are managed as an example +struct ChannelSettings { + // 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. + + /// + /// If zero then, use default max legal continuous power (ie. something that won't + /// burn out the radio hardware) + /// In most cases you should use zero here. + /// Units are in dBm. + var txPower: Int32 = 0 + + /// + /// Note: This is the 'old' mechanism for specifying channel parameters. + /// Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH. + /// As a heuristic: If bandwidth is specified, do not use modem_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 modemConfig: ChannelSettings.ModemConfig = .bw125Cr45Sf128 + + /// + /// Bandwidth in MHz + /// Certain bandwidth numbers are 'special' and will be converted to the + /// appropriate floating point value: 31 -> 31.25MHz + var bandwidth: UInt32 = 0 + + /// + /// A number from 7 to 12. + /// Indicates number of chirps per symbol as 1<=4.2) + +extension ChannelSettings.ModemConfig: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [ChannelSettings.ModemConfig] = [ + .bw125Cr45Sf128, + .bw500Cr45Sf128, + .bw3125Cr48Sf512, + .bw125Cr48Sf4096, + ] +} + +#endif // swift(>=4.2) + +/// +/// A pair of a channel number, mode and the (sharable) settings for that channel +struct Channel { + // 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. + + /// + /// The index of this channel in the channel table (from 0 to MAX_NUM_CHANNELS-1) + /// (Someday - not currently implemented) An index of -1 could be used to mean "set by name", + /// in which case the target node will find and set the channel by settings.name. + var index: Int32 = 0 + + /// + /// The new settings, or NULL to disable that channel + var settings: ChannelSettings { + get {return _settings ?? ChannelSettings()} + set {_settings = newValue} + } + /// Returns true if `settings` has been explicitly set. + var hasSettings: Bool {return self._settings != nil} + /// Clears the value of `settings`. Subsequent reads from it will return its default value. + mutating func clearSettings() {self._settings = nil} + + var role: Channel.Role = .disabled + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// + /// How this channel is being used (or not). + /// + /// Note: this field is an enum to give us options for the future. + /// In particular, someday we might make a 'SCANNING' option. + /// SCANNING channels could have different frequencies and the radio would + /// occasionally check that freq to see if anything is being transmitted. + /// + /// For devices that have multiple physical radios attached, we could keep multiple PRIMARY/SCANNING channels active at once to allow + /// cross band routing as needed. + /// If a device has only a single radio (the common case) only one channel can be PRIMARY at a time + /// (but any number of SECONDARY channels can't be sent received on that common frequency) + enum Role: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// This channel is not in use right now + case disabled // = 0 + + /// + /// This channel is used to set the frequency for the radio - all other enabled channels must be SECONDARY + case primary // = 1 + + /// + /// Secondary channels are only used for encryption/decryption/authentication purposes. + /// Their radio settings (freq etc) are ignored, only psk is used. + case secondary // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .disabled + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .disabled + case 1: self = .primary + case 2: self = .secondary + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .disabled: return 0 + case .primary: return 1 + case .secondary: return 2 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} + + fileprivate var _settings: ChannelSettings? = nil +} + +#if swift(>=4.2) + +extension Channel.Role: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [Channel.Role] = [ + .disabled, + .primary, + .secondary, + ] +} + +#endif // swift(>=4.2) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension ChannelSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ChannelSettings" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "tx_power"), + 3: .standard(proto: "modem_config"), + 6: .same(proto: "bandwidth"), + 7: .standard(proto: "spread_factor"), + 8: .standard(proto: "coding_rate"), + 9: .standard(proto: "channel_num"), + 4: .same(proto: "psk"), + 5: .same(proto: "name"), + 10: .same(proto: "id"), + 16: .standard(proto: "uplink_enabled"), + 17: .standard(proto: "downlink_enabled"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularInt32Field(value: &self.txPower) }() + case 3: try { try decoder.decodeSingularEnumField(value: &self.modemConfig) }() + case 4: try { try decoder.decodeSingularBytesField(value: &self.psk) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.name) }() + case 6: try { try decoder.decodeSingularUInt32Field(value: &self.bandwidth) }() + case 7: try { try decoder.decodeSingularUInt32Field(value: &self.spreadFactor) }() + case 8: try { try decoder.decodeSingularUInt32Field(value: &self.codingRate) }() + case 9: try { try decoder.decodeSingularUInt32Field(value: &self.channelNum) }() + case 10: try { try decoder.decodeSingularFixed32Field(value: &self.id) }() + case 16: try { try decoder.decodeSingularBoolField(value: &self.uplinkEnabled) }() + case 17: try { try decoder.decodeSingularBoolField(value: &self.downlinkEnabled) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.txPower != 0 { + try visitor.visitSingularInt32Field(value: self.txPower, fieldNumber: 1) + } + if self.modemConfig != .bw125Cr45Sf128 { + try visitor.visitSingularEnumField(value: self.modemConfig, fieldNumber: 3) + } + if !self.psk.isEmpty { + try visitor.visitSingularBytesField(value: self.psk, fieldNumber: 4) + } + if !self.name.isEmpty { + try visitor.visitSingularStringField(value: self.name, fieldNumber: 5) + } + if self.bandwidth != 0 { + try visitor.visitSingularUInt32Field(value: self.bandwidth, fieldNumber: 6) + } + if self.spreadFactor != 0 { + try visitor.visitSingularUInt32Field(value: self.spreadFactor, fieldNumber: 7) + } + if self.codingRate != 0 { + try visitor.visitSingularUInt32Field(value: self.codingRate, fieldNumber: 8) + } + if self.channelNum != 0 { + try visitor.visitSingularUInt32Field(value: self.channelNum, fieldNumber: 9) + } + if self.id != 0 { + try visitor.visitSingularFixed32Field(value: self.id, fieldNumber: 10) + } + if self.uplinkEnabled != false { + try visitor.visitSingularBoolField(value: self.uplinkEnabled, fieldNumber: 16) + } + if self.downlinkEnabled != false { + try visitor.visitSingularBoolField(value: self.downlinkEnabled, fieldNumber: 17) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ChannelSettings, rhs: ChannelSettings) -> Bool { + if lhs.txPower != rhs.txPower {return false} + if lhs.modemConfig != rhs.modemConfig {return false} + if lhs.bandwidth != rhs.bandwidth {return false} + if lhs.spreadFactor != rhs.spreadFactor {return false} + if lhs.codingRate != rhs.codingRate {return false} + if lhs.channelNum != rhs.channelNum {return false} + if lhs.psk != rhs.psk {return false} + if lhs.name != rhs.name {return false} + if lhs.id != rhs.id {return false} + if lhs.uplinkEnabled != rhs.uplinkEnabled {return false} + if lhs.downlinkEnabled != rhs.downlinkEnabled {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ChannelSettings.ModemConfig: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "Bw125Cr45Sf128"), + 1: .same(proto: "Bw500Cr45Sf128"), + 2: .same(proto: "Bw31_25Cr48Sf512"), + 3: .same(proto: "Bw125Cr48Sf4096"), + ] +} + +extension Channel: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Channel" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "index"), + 2: .same(proto: "settings"), + 3: .same(proto: "role"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularInt32Field(value: &self.index) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._settings) }() + case 3: try { try decoder.decodeSingularEnumField(value: &self.role) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.index != 0 { + try visitor.visitSingularInt32Field(value: self.index, fieldNumber: 1) + } + if let v = self._settings { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } + if self.role != .disabled { + try visitor.visitSingularEnumField(value: self.role, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Channel, rhs: Channel) -> Bool { + if lhs.index != rhs.index {return false} + if lhs._settings != rhs._settings {return false} + if lhs.role != rhs.role {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Channel.Role: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "DISABLED"), + 1: .same(proto: "PRIMARY"), + 2: .same(proto: "SECONDARY"), + ] +} diff --git a/MeshtasticClient/Protobufs/deviceonly.pb.swift b/MeshtasticClient/Protobufs/deviceonly.pb.swift new file mode 100644 index 00000000..b44ea5c8 --- /dev/null +++ b/MeshtasticClient/Protobufs/deviceonly.pb.swift @@ -0,0 +1,402 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: deviceonly.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// This is a stub version of the old 1.1 representation of RadioConfig. +/// But only keeping the region info. +/// The device firmware uses this stub while migrating old nodes to the new preferences system. +struct LegacyRadioConfig { + // 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. + + var preferences: LegacyRadioConfig.LegacyPreferences { + get {return _preferences ?? LegacyRadioConfig.LegacyPreferences()} + set {_preferences = newValue} + } + /// Returns true if `preferences` has been explicitly set. + var hasPreferences: Bool {return self._preferences != nil} + /// Clears the value of `preferences`. Subsequent reads from it will return its default value. + mutating func clearPreferences() {self._preferences = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + struct LegacyPreferences { + // 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. + + /// + /// The region code for my radio (US, CN, EU433, etc...) + var region: RegionCode = .unset + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} + + fileprivate var _preferences: LegacyRadioConfig.LegacyPreferences? = nil +} + +/// +/// This message is never sent over the wire, but it is used for serializing DB +/// state to flash in the device code +/// FIXME, since we write this each time we enter deep sleep (and have infinite +/// flash) it would be better to use some sort of append only data structure for +/// the receive queue and use the preferences store for the other stuff +struct DeviceState { + // 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. + + /// + /// Moved to its own file, but we keep this here so we can automatically migrate old radio.region settings + var legacyRadio: LegacyRadioConfig { + get {return _storage._legacyRadio ?? LegacyRadioConfig()} + set {_uniqueStorage()._legacyRadio = newValue} + } + /// Returns true if `legacyRadio` has been explicitly set. + var hasLegacyRadio: Bool {return _storage._legacyRadio != nil} + /// Clears the value of `legacyRadio`. Subsequent reads from it will return its default value. + mutating func clearLegacyRadio() {_uniqueStorage()._legacyRadio = nil} + + /// + /// Read only settings/info about this node + var myNode: MyNodeInfo { + get {return _storage._myNode ?? MyNodeInfo()} + set {_uniqueStorage()._myNode = newValue} + } + /// Returns true if `myNode` has been explicitly set. + var hasMyNode: Bool {return _storage._myNode != nil} + /// Clears the value of `myNode`. Subsequent reads from it will return its default value. + mutating func clearMyNode() {_uniqueStorage()._myNode = nil} + + /// + /// My owner info + var owner: User { + get {return _storage._owner ?? User()} + set {_uniqueStorage()._owner = newValue} + } + /// Returns true if `owner` has been explicitly set. + var hasOwner: Bool {return _storage._owner != nil} + /// Clears the value of `owner`. Subsequent reads from it will return its default value. + mutating func clearOwner() {_uniqueStorage()._owner = nil} + + var nodeDb: [NodeInfo] { + get {return _storage._nodeDb} + set {_uniqueStorage()._nodeDb = newValue} + } + + /// + /// Received packets saved for delivery to the phone + var receiveQueue: [MeshPacket] { + get {return _storage._receiveQueue} + set {_uniqueStorage()._receiveQueue = newValue} + } + + /// + /// A version integer used to invalidate old save files when we make + /// incompatible changes This integer is set at build time and is private to + /// NodeDB.cpp in the device code. + var version: UInt32 { + get {return _storage._version} + set {_uniqueStorage()._version = newValue} + } + + /// + /// We keep the last received text message (only) stored in the device flash, + /// so we can show it on the screen. + /// Might be null + var rxTextMessage: MeshPacket { + get {return _storage._rxTextMessage ?? MeshPacket()} + set {_uniqueStorage()._rxTextMessage = newValue} + } + /// Returns true if `rxTextMessage` has been explicitly set. + var hasRxTextMessage: Bool {return _storage._rxTextMessage != nil} + /// Clears the value of `rxTextMessage`. Subsequent reads from it will return its default value. + mutating func clearRxTextMessage() {_uniqueStorage()._rxTextMessage = nil} + + /// + /// Used only during development. + /// Indicates developer is testing and changes should never be saved to flash. + var noSave: Bool { + get {return _storage._noSave} + set {_uniqueStorage()._noSave = newValue} + } + + /// + /// Some GPSes seem to have bogus settings from the factory, so we always do one factory reset. + var didGpsReset: Bool { + get {return _storage._didGpsReset} + set {_uniqueStorage()._didGpsReset = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +/// +/// The on-disk saved channels +struct ChannelFile { + // 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. + + /// + /// The channels our node knows about + var channels: [Channel] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension LegacyRadioConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "LegacyRadioConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "preferences"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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: &self._preferences) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._preferences { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: LegacyRadioConfig, rhs: LegacyRadioConfig) -> Bool { + if lhs._preferences != rhs._preferences {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension LegacyRadioConfig.LegacyPreferences: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = LegacyRadioConfig.protoMessageName + ".LegacyPreferences" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 15: .same(proto: "region"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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 15: try { try decoder.decodeSingularEnumField(value: &self.region) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.region != .unset { + try visitor.visitSingularEnumField(value: self.region, fieldNumber: 15) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: LegacyRadioConfig.LegacyPreferences, rhs: LegacyRadioConfig.LegacyPreferences) -> Bool { + if lhs.region != rhs.region {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "DeviceState" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "legacyRadio"), + 2: .standard(proto: "my_node"), + 3: .same(proto: "owner"), + 4: .standard(proto: "node_db"), + 5: .standard(proto: "receive_queue"), + 8: .same(proto: "version"), + 7: .standard(proto: "rx_text_message"), + 9: .standard(proto: "no_save"), + 11: .standard(proto: "did_gps_reset"), + ] + + fileprivate class _StorageClass { + var _legacyRadio: LegacyRadioConfig? = nil + var _myNode: MyNodeInfo? = nil + var _owner: User? = nil + var _nodeDb: [NodeInfo] = [] + var _receiveQueue: [MeshPacket] = [] + var _version: UInt32 = 0 + var _rxTextMessage: MeshPacket? = nil + var _noSave: Bool = false + var _didGpsReset: Bool = false + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _legacyRadio = source._legacyRadio + _myNode = source._myNode + _owner = source._owner + _nodeDb = source._nodeDb + _receiveQueue = source._receiveQueue + _version = source._version + _rxTextMessage = source._rxTextMessage + _noSave = source._noSave + _didGpsReset = source._didGpsReset + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(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._legacyRadio) }() + case 2: try { try decoder.decodeSingularMessageField(value: &_storage._myNode) }() + case 3: try { try decoder.decodeSingularMessageField(value: &_storage._owner) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &_storage._nodeDb) }() + case 5: try { try decoder.decodeRepeatedMessageField(value: &_storage._receiveQueue) }() + case 7: try { try decoder.decodeSingularMessageField(value: &_storage._rxTextMessage) }() + case 8: try { try decoder.decodeSingularUInt32Field(value: &_storage._version) }() + case 9: try { try decoder.decodeSingularBoolField(value: &_storage._noSave) }() + case 11: try { try decoder.decodeSingularBoolField(value: &_storage._didGpsReset) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if let v = _storage._legacyRadio { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if let v = _storage._myNode { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } + if let v = _storage._owner { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } + if !_storage._nodeDb.isEmpty { + try visitor.visitRepeatedMessageField(value: _storage._nodeDb, fieldNumber: 4) + } + if !_storage._receiveQueue.isEmpty { + try visitor.visitRepeatedMessageField(value: _storage._receiveQueue, fieldNumber: 5) + } + if let v = _storage._rxTextMessage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + } + if _storage._version != 0 { + try visitor.visitSingularUInt32Field(value: _storage._version, fieldNumber: 8) + } + if _storage._noSave != false { + try visitor.visitSingularBoolField(value: _storage._noSave, fieldNumber: 9) + } + if _storage._didGpsReset != false { + try visitor.visitSingularBoolField(value: _storage._didGpsReset, fieldNumber: 11) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: DeviceState, rhs: DeviceState) -> 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._legacyRadio != rhs_storage._legacyRadio {return false} + if _storage._myNode != rhs_storage._myNode {return false} + if _storage._owner != rhs_storage._owner {return false} + if _storage._nodeDb != rhs_storage._nodeDb {return false} + if _storage._receiveQueue != rhs_storage._receiveQueue {return false} + if _storage._version != rhs_storage._version {return false} + if _storage._rxTextMessage != rhs_storage._rxTextMessage {return false} + if _storage._noSave != rhs_storage._noSave {return false} + if _storage._didGpsReset != rhs_storage._didGpsReset {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ChannelFile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ChannelFile" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "channels"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeRepeatedMessageField(value: &self.channels) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.channels.isEmpty { + try visitor.visitRepeatedMessageField(value: self.channels, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ChannelFile, rhs: ChannelFile) -> Bool { + if lhs.channels != rhs.channels {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticClient/Protobufs/environmental_measurement.pb.swift b/MeshtasticClient/Protobufs/environmental_measurement.pb.swift new file mode 100644 index 00000000..73e7ef02 --- /dev/null +++ b/MeshtasticClient/Protobufs/environmental_measurement.pb.swift @@ -0,0 +1,83 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: environmental_measurement.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +struct EnvironmentalMeasurement { + // 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. + + var temperature: Float = 0 + + var relativeHumidity: Float = 0 + + var barometricPressure: Float = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension EnvironmentalMeasurement: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "EnvironmentalMeasurement" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "temperature"), + 2: .standard(proto: "relative_humidity"), + 3: .standard(proto: "barometric_pressure"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularFloatField(value: &self.temperature) }() + case 2: try { try decoder.decodeSingularFloatField(value: &self.relativeHumidity) }() + case 3: try { try decoder.decodeSingularFloatField(value: &self.barometricPressure) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.temperature != 0 { + try visitor.visitSingularFloatField(value: self.temperature, fieldNumber: 1) + } + if self.relativeHumidity != 0 { + try visitor.visitSingularFloatField(value: self.relativeHumidity, fieldNumber: 2) + } + if self.barometricPressure != 0 { + try visitor.visitSingularFloatField(value: self.barometricPressure, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: EnvironmentalMeasurement, rhs: EnvironmentalMeasurement) -> Bool { + if lhs.temperature != rhs.temperature {return false} + if lhs.relativeHumidity != rhs.relativeHumidity {return false} + if lhs.barometricPressure != rhs.barometricPressure {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticClient/Protobufs/mesh.pb.swift b/MeshtasticClient/Protobufs/mesh.pb.swift new file mode 100644 index 00000000..4a43e8af --- /dev/null +++ b/MeshtasticClient/Protobufs/mesh.pb.swift @@ -0,0 +1,2496 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: mesh.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +/// +/// Meshtastic protobufs +/// +/// For more information on protobufs (and tools to use them with the language of your choice) see +/// https://developers.google.com/protocol-buffers/docs/proto3 +/// +/// We are not placing any of these defs inside a package, because if you do the +/// resulting nanopb version is super verbose package mesh. +/// +/// Protobuf build instructions: +/// +/// To build java classes for reading writing: +/// protoc -I=. --java_out /tmp mesh.proto +/// +/// To generate Nanopb c code: +/// /home/kevinh/packages/nanopb-0.4.0-linux-x86/generator-bin/protoc --nanopb_out=/tmp -I=app/src/main/proto mesh.proto +/// +/// Nanopb binaries available here: https://jpa.kapsi.fi/nanopb/download/ use nanopb 0.4.0 + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// Note: these enum names must EXACTLY match the string used in the device +/// bin/build-all.sh script. +/// Because they will be used to find firmware filenames in the android app for OTA updates. +/// To match the old style filenames, _ is converted to -, p is converted to . +enum HardwareModel: SwiftProtobuf.Enum { + typealias RawValue = Int + case unset // = 0 + case tloraV2 // = 1 + case tloraV1 // = 2 + case tloraV211P6 // = 3 + case tbeam // = 4 + + /// The original heltec WiFi_Lora_32_V2, which had battery voltage sensing hooked to GPIO 13 (see HELTEC_V2 for the new version). + case heltecV20 // = 5 + case tbeam0P7 // = 6 + case tEcho // = 7 + case tloraV11P3 // = 8 + case rak4631 // = 9 + + /// The new version of the heltec WiFi_Lora_32_V2 board that has battery sensing hooked to GPIO 37. Sadly they did not update anything on the silkscreen to identify this board + case heltecV21 // = 10 + + /// + /// Less common/prototype boards listed here (needs one more byte over the air) + case loraRelayV1 // = 32 + case nrf52840Dk // = 33 + case ppr // = 34 + case genieblocks // = 35 + case nrf52Unknown // = 36 + case portduino // = 37 + + /// + /// The simulator built into the android app + case androidSim // = 38 + case UNRECOGNIZED(Int) + + init() { + self = .unset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 1: self = .tloraV2 + case 2: self = .tloraV1 + case 3: self = .tloraV211P6 + case 4: self = .tbeam + case 5: self = .heltecV20 + case 6: self = .tbeam0P7 + case 7: self = .tEcho + case 8: self = .tloraV11P3 + case 9: self = .rak4631 + case 10: self = .heltecV21 + case 32: self = .loraRelayV1 + case 33: self = .nrf52840Dk + case 34: self = .ppr + case 35: self = .genieblocks + case 36: self = .nrf52Unknown + case 37: self = .portduino + case 38: self = .androidSim + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unset: return 0 + case .tloraV2: return 1 + case .tloraV1: return 2 + case .tloraV211P6: return 3 + case .tbeam: return 4 + case .heltecV20: return 5 + case .tbeam0P7: return 6 + case .tEcho: return 7 + case .tloraV11P3: return 8 + case .rak4631: return 9 + case .heltecV21: return 10 + case .loraRelayV1: return 32 + case .nrf52840Dk: return 33 + case .ppr: return 34 + case .genieblocks: return 35 + case .nrf52Unknown: return 36 + case .portduino: return 37 + case .androidSim: return 38 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension HardwareModel: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [HardwareModel] = [ + .unset, + .tloraV2, + .tloraV1, + .tloraV211P6, + .tbeam, + .heltecV20, + .tbeam0P7, + .tEcho, + .tloraV11P3, + .rak4631, + .heltecV21, + .loraRelayV1, + .nrf52840Dk, + .ppr, + .genieblocks, + .nrf52Unknown, + .portduino, + .androidSim, + ] +} + +#endif // swift(>=4.2) + +/// +/// Shared constants between device and phone +enum Constants: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// First enum must be zero, and we are just using this enum to + /// pass int constants between two very different environments + case unused // = 0 + + /// + /// From mesh.options + /// note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is + /// outside of this envelope + case dataPayloadLen // = 237 + case UNRECOGNIZED(Int) + + init() { + self = .unused + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unused + case 237: self = .dataPayloadLen + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unused: return 0 + case .dataPayloadLen: return 237 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension Constants: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [Constants] = [ + .unused, + .dataPayloadLen, + ] +} + +#endif // swift(>=4.2) + +/// +/// Error codes for critical errors +/// +/// The device might report these fault codes on the screen. +/// If you encounter a fault code, please post on the meshtastic.discourse.group +/// and we'll try to help. +enum CriticalErrorCode: SwiftProtobuf.Enum { + typealias RawValue = Int + case none // = 0 + + /// + /// A software bug was detected while trying to send lora + case txWatchdog // = 1 + + /// + /// A software bug was detected on entry to sleep + case sleepEnterWait // = 2 + + /// + /// No Lora radio hardware could be found + case noRadio // = 3 + + /// + /// Not normally used + case unspecified // = 4 + + /// + /// We failed while configuring a UBlox GPS + case ubloxInitFailed // = 5 + + /// + /// This board was expected to have a power management chip and it is missing or broken + case noAxp192 // = 6 + + /// + /// The channel tried to set a radio setting which is not supported by this chipset, + /// radio comms settings are now undefined. + case invalidRadioSetting // = 7 + + /// + /// Radio transmit hardware failure. We sent data to the radio chip, but it didn't + /// reply with an interrupt. + case transmitFailed // = 8 + + /// + /// We detected that the main CPU voltage dropped below the minumum acceptable value + case brownout // = 9 + + /// Selftest of SX1262 radio chip failed + case sx1262Failure // = 10 + + /// A (likely software but possibly hardware) failure was detected while trying to send packets. If this occurs on your board, please + ///post in the forum so that we can ask you to collect some information to allow fixing this bug + case radioSpiBug // = 11 + case UNRECOGNIZED(Int) + + init() { + self = .none + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .none + case 1: self = .txWatchdog + case 2: self = .sleepEnterWait + case 3: self = .noRadio + case 4: self = .unspecified + case 5: self = .ubloxInitFailed + case 6: self = .noAxp192 + case 7: self = .invalidRadioSetting + case 8: self = .transmitFailed + case 9: self = .brownout + case 10: self = .sx1262Failure + case 11: self = .radioSpiBug + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .none: return 0 + case .txWatchdog: return 1 + case .sleepEnterWait: return 2 + case .noRadio: return 3 + case .unspecified: return 4 + case .ubloxInitFailed: return 5 + case .noAxp192: return 6 + case .invalidRadioSetting: return 7 + case .transmitFailed: return 8 + case .brownout: return 9 + case .sx1262Failure: return 10 + case .radioSpiBug: return 11 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension CriticalErrorCode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [CriticalErrorCode] = [ + .none, + .txWatchdog, + .sleepEnterWait, + .noRadio, + .unspecified, + .ubloxInitFailed, + .noAxp192, + .invalidRadioSetting, + .transmitFailed, + .brownout, + .sx1262Failure, + .radioSpiBug, + ] +} + +#endif // swift(>=4.2) + +/// +/// a gps position +struct Position { + // 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. + + /// + /// The new preferred location encoding, divide by 1e-7 to get degrees + /// in floating point + var latitudeI: Int32 = 0 + + var longitudeI: Int32 = 0 + + /// + /// In meters above MSL + var altitude: Int32 = 0 + + /// + /// 1-100 (0 means not provided) + var batteryLevel: Int32 = 0 + + /// + /// This is usually not sent over the mesh (to save space), but it is sent + /// from the phone so that the local device can set its RTC If it is sent over + /// the mesh (because there are devices on the mesh without GPS), it will only + /// be sent by devices which has a hardware GPS clock. + /// seconds since 1970 + var time: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// +/// Broadcast when a newly powered mesh node wants to find a node num it can use +/// Sent from the phone over bluetooth to set the user id for the owner of this node. +/// Also sent from nodes to each other when a new node signs on (so all clients can have this info) +/// +/// The algorithm is as follows: +/// when a node starts up, it broadcasts their user and the normal flow is for all +/// other nodes to reply with their User as well (so the new node can build its nodedb) +/// If a node ever receives a User (not just the first broadcast) message where +/// the sender node number equals our node number, that indicates a collision has +/// occurred and the following steps should happen: +/// +/// If the receiving node (that was already in the mesh)'s macaddr is LOWER than the +/// new User who just tried to sign in: it gets to keep its nodenum. +/// We send a broadcast message of OUR User (we use a broadcast so that the other node can +/// receive our message, considering we have the same id - it also serves to let +/// observers correct their nodedb) - this case is rare so it should be okay. +/// +/// If any node receives a User where the macaddr is GTE than their local macaddr, +/// they have been vetoed and should pick a new random nodenum (filtering against +/// whatever it knows about the nodedb) and rebroadcast their User. +/// +/// A few nodenums are reserved and will never be requested: +/// 0xff - broadcast +/// 0 through 3 - for future use +struct User { + // 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. + + /// + /// A globally unique ID string for this user. + /// In the case of Signal that would mean +16504442323, for the default macaddr derived id it would be !<8 hexidecimal bytes>. + /// Note: app developers are encouraged to also use the following standard + /// node IDs "^all" (for broadcast), "^local" (for the locally connected node) + var id: String = String() + + /// + /// A full name for this user, i.e. "Kevin Hester" + var longName: String = String() + + /// + /// A VERY short name, ideally two characters. + /// Suitable for a tiny OLED screen + var shortName: String = String() + + /// + /// This is the addr of the radio. + /// Not populated by the phone, but added by the esp32 when broadcasting + var macaddr: Data = Data() + + /// + /// TBEAM, HELTEC, etc... + /// Starting in 1.2.11 moved to hw_model enum in the NodeInfo object. + /// Apps will still need the string here for older builds + /// (so OTA update can find the right image), but if the enum is available it will be used instead. + var hwModel: HardwareModel = .unset + + /// + /// In some regions HAM radio operators have different bandwidth limitations than others. + /// If this user is a licensed operator, set this flag. + /// Also, "long_name" should be their licence number. + var isLicensed: Bool = false + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// +/// A message used in our Dynamic Source Routing protocol (RFC 4728 based) +struct RouteDiscovery { + // 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. + + /// + /// The list of nodenums this packet has visited so far + var route: [UInt32] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// +///A Routing control Data packet handled by the routing plugin +struct Routing { + // 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. + + var variant: Routing.OneOf_Variant? = nil + + /// + /// A route request going from the requester + var routeRequest: RouteDiscovery { + get { + if case .routeRequest(let v)? = variant {return v} + return RouteDiscovery() + } + set {variant = .routeRequest(newValue)} + } + + /// + /// A route reply + var routeReply: RouteDiscovery { + get { + if case .routeReply(let v)? = variant {return v} + return RouteDiscovery() + } + set {variant = .routeReply(newValue)} + } + + /// + /// A failure in delivering a message (usually used for routing control messages, but might be provided + /// in addition to ack.fail_id to provide details on the type of failure). + var errorReason: Routing.Error { + get { + if case .errorReason(let v)? = variant {return v} + return .none + } + set {variant = .errorReason(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum OneOf_Variant: Equatable { + /// + /// A route request going from the requester + case routeRequest(RouteDiscovery) + /// + /// A route reply + case routeReply(RouteDiscovery) + /// + /// A failure in delivering a message (usually used for routing control messages, but might be provided + /// in addition to ack.fail_id to provide details on the type of failure). + case errorReason(Routing.Error) + + #if !swift(>=4.1) + static func ==(lhs: Routing.OneOf_Variant, rhs: Routing.OneOf_Variant) -> 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 (.routeRequest, .routeRequest): return { + guard case .routeRequest(let l) = lhs, case .routeRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.routeReply, .routeReply): return { + guard case .routeReply(let l) = lhs, case .routeReply(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.errorReason, .errorReason): return { + guard case .errorReason(let l) = lhs, case .errorReason(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + /// + /// A failure in delivering a message (usually used for routing control messages, but might be provided in addition to ack.fail_id to provide + /// details on the type of failure). + enum Error: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// This message is not a failure + case none // = 0 + + /// + /// Our node doesn't have a route to the requested destination anymore. + case noRoute // = 1 + + /// + /// We received a nak while trying to forward on your behalf + case gotNak // = 2 + case timeout // = 3 + + /// + /// No suitable interface could be found for delivering this packet + case noInterface // = 4 + + /// + /// We reached the max retransmission count (typically for naive flood routing) + case maxRetransmit // = 5 + + /// + /// No suitable channel was found for sending this packet (i.e. was requested channel index disabled?) + case noChannel // = 6 + + /// + /// The packet was too big for sending (exceeds interface MTU after encoding) + case tooLarge // = 7 + + /// + /// 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 noResponse // = 8 + + /// + /// The application layer service on the remote node received your request, but considered your request somehow invalid + case badRequest // = 32 + + /// + /// 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) + case notAuthorized // = 33 + case UNRECOGNIZED(Int) + + init() { + self = .none + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .none + case 1: self = .noRoute + case 2: self = .gotNak + case 3: self = .timeout + case 4: self = .noInterface + case 5: self = .maxRetransmit + case 6: self = .noChannel + case 7: self = .tooLarge + case 8: self = .noResponse + case 32: self = .badRequest + case 33: self = .notAuthorized + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .none: return 0 + case .noRoute: return 1 + case .gotNak: return 2 + case .timeout: return 3 + case .noInterface: return 4 + case .maxRetransmit: return 5 + case .noChannel: return 6 + case .tooLarge: return 7 + case .noResponse: return 8 + case .badRequest: return 32 + case .notAuthorized: return 33 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension Routing.Error: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [Routing.Error] = [ + .none, + .noRoute, + .gotNak, + .timeout, + .noInterface, + .maxRetransmit, + .noChannel, + .tooLarge, + .noResponse, + .badRequest, + .notAuthorized, + ] +} + +#endif // swift(>=4.2) + +/// +/// (Formerly called SubPacket) +/// The payload portion fo a packet, this is the actual bytes that are sent +/// inside a radio packet (because from/to are broken out by the comms library) +struct DataMessage { + // 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. + + /// + /// Formerly named typ and of type Type + var portnum: PortNum = .unknownApp + + /// + /// Required + var payload: Data = Data() + + /// + /// Not normally used, but for testing a sender can request that recipient + /// responds in kind (i.e. if it received a position, it should unicast back it's position). + /// Note: that if you set this on a broadcast you will receive many replies. + var wantResponse: Bool = false + + /// + /// The address of the destination node. + /// This field is is filled in by the mesh radio device software, application + /// layer software should never need it. + /// RouteDiscovery messages _must_ populate this. + /// Other message types might need to if they are doing multihop routing. + var dest: UInt32 = 0 + + /// + /// The address of the original sender for this message. + /// This field should _only_ be populated for reliable multihop packets (to keep + /// packets small). + var source: UInt32 = 0 + + /// + /// Only used in routing or response messages. + /// Indicates the original message ID that this message is reporting failure on. (formerly called original_id) + var requestID: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// +/// A packet envelope sent/received over the mesh +/// only payloadVariant is sent in the payload portion of the LORA packet. +/// The other fields are either not sent at all, or sent in the special 16 byte LORA header. +struct MeshPacket { + // 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. + + /// + /// The sending node number. + /// Note: Our crypto implementation uses this field as well. + /// See [crypto](/developers/device/encryption.md) for details. + /// FIXME - really should be fixed32 instead, this encoding only hurts the ble link though. + var from: UInt32 = 0 + + /// + /// The (immediatSee Priority description for more details.y should be fixed32 instead, this encoding only + /// hurts the ble link though. + var to: UInt32 = 0 + + /// + /// (Usually) If set, this indicates the index in the secondary_channels table that this packet was sent/received on. + /// If unset, packet was on the primary channel. + /// A particular node might know only a subset of channels in use on the mesh. + /// Therefore channel_index is inherently a local concept and meaningless to send between nodes. + /// Very briefly, while sending and receiving deep inside the device Router code, this field instead + /// contains the 'channel hash' instead of the index. + /// This 'trick' is only used while the payloadVariant is an 'encrypted'. + var channel: UInt32 = 0 + + var payloadVariant: MeshPacket.OneOf_PayloadVariant? = nil + + var decoded: DataMessage { + get { + if case .decoded(let v)? = payloadVariant {return v} + return DataMessage() + } + set {payloadVariant = .decoded(newValue)} + } + + var encrypted: Data { + get { + if case .encrypted(let v)? = payloadVariant {return v} + return Data() + } + set {payloadVariant = .encrypted(newValue)} + } + + /// + /// A unique ID for this packet. + /// Always 0 for no-ack packets or non broadcast packets (and therefore take zero bytes of space). + /// Otherwise a unique ID for this packet, useful for flooding algorithms. + /// ID only needs to be unique on a _per sender_ basis, and it only + /// needs to be unique for a few minutes (long enough to last for the length of + /// any ACK or the completion of a mesh broadcast flood). + /// Note: Our crypto implementation uses this id as well. + /// See [crypto](/developers/device/encryption.md) for details. + /// FIXME - really should be fixed32 instead, this encoding only + /// hurts the ble link though. + var id: UInt32 = 0 + + /// + /// The time this message was received by the esp32 (secs since 1970). + /// Note: this field is _never_ sent on the radio link itself (to save space) Times + /// are typically not sent over the mesh, but they will be added to any Packet + /// (chain of SubPacket) sent to the phone (so the phone can know exact time of reception) + var rxTime: UInt32 = 0 + + /// + /// *Never* sent over the radio links. + /// Set during reception to indicate the SNR of this packet. + /// Used to collect statistics on current link quality. + var rxSnr: Float = 0 + + /// + /// If unset treated as zero (no forwarding, send to adjacent nodes only) + /// if 1, allow hopping through one node, etc... + /// For our usecase real world topologies probably have a max of about 3. + /// This field is normally placed into a few of bits in the header. + var hopLimit: UInt32 = 0 + + /// + /// This packet is being sent as a reliable message, we would prefer it to arrive at the destination. + /// We would like to receive a ack packet in response. + /// Broadcasts messages treat this flag specially: Since acks for broadcasts would + /// rapidly flood the channel, the normal ack behavior is suppressed. + /// Instead, the original sender listens to see if at least one node is rebroadcasting this packet (because naive flooding algorithm). + /// If it hears that the odds (given typical LoRa topologies) the odds are very high that every node should eventually receive the message. + /// So FloodingRouter.cpp generates an implicit ack which is delivered to the original sender. + /// If after some time we don't hear anyone rebroadcast our packet, we will timeout and retransmit, using the regular resend logic. + /// Note: This flag is normally sent in a flag bit in the header when sent over the wire + var wantAck: Bool = false + + /// + /// The priority of this message for sending. + /// See MeshPacket.Priority description for more details. + var priority: MeshPacket.Priority = .unset + + /// + /// rssi of received packet. Only sent to phone for dispay purposes. + var rxRssi: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum OneOf_PayloadVariant: Equatable { + case decoded(DataMessage) + case encrypted(Data) + + #if !swift(>=4.1) + static func ==(lhs: MeshPacket.OneOf_PayloadVariant, rhs: MeshPacket.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 (.decoded, .decoded): return { + guard case .decoded(let l) = lhs, case .decoded(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.encrypted, .encrypted): return { + guard case .encrypted(let l) = lhs, case .encrypted(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + /// + /// The priority of this message for sending. + /// Higher priorities are sent first (when managing the transmit queue). + /// This field is never sent over the air, it is only used internally inside of a local device node. + /// API clients (either on the local node or connected directly to the node) + /// can set this parameter if necessary. + /// + /// (values must be <= 127 to keep protobuf field to one byte in size. + /// + /// Detailed background on this field: + /// + /// I noticed a funny side effect of lora being so slow: Usually when making + /// a protocol there isn’t much need to use message priority to change the order + /// of transmission (because interfaces are fairly fast). + /// But for lora where packets can take a few seconds each, it is very important + /// to make sure that critical packets are sent ASAP. + /// In the case of meshtastic that means we want to send protocol acks as soon as possible + /// (to prevent unneeded retransmissions), we want routing messages to be sent next, + /// then messages marked as reliable and finally ‘background’ packets like periodic position updates. + /// + /// So I bit the bullet and implemented a new (internal - not sent over the air) + /// field in MeshPacket called ‘priority’. + /// And the transmission queue in the router object is now a priority queue. + enum Priority: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// Treated as Priority.DEFAULT + case unset // = 0 + case min // = 1 + + /// + /// Background position updates are sent with very low priority - + /// if the link is super congested they might not go out at all + case background // = 10 + + /// + /// This priority is used for most messages that don't have a priority set + case `default` // = 64 + + /// + /// If priority is unset but the message is marked as want_ack, + /// assume it is important and use a slightly higher priority + case reliable // = 70 + + /// + /// Ack/naks are sent with very high priority to ensure that retransmission + /// stops as soon as possible + case ack // = 120 + case max // = 127 + case UNRECOGNIZED(Int) + + init() { + self = .unset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 1: self = .min + case 10: self = .background + case 64: self = .default + case 70: self = .reliable + case 120: self = .ack + case 127: self = .max + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unset: return 0 + case .min: return 1 + case .background: return 10 + case .default: return 64 + case .reliable: return 70 + case .ack: return 120 + case .max: return 127 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension MeshPacket.Priority: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [MeshPacket.Priority] = [ + .unset, + .min, + .background, + .default, + .reliable, + .ack, + .max, + ] +} + +#endif // swift(>=4.2) + +/// +/// The bluetooth to device link: +/// +/// Old BTLE protocol docs from TODO, merge in above and make real docs... +/// +/// use protocol buffers, and NanoPB +/// +/// messages from device to phone: +/// POSITION_UPDATE (..., time) +/// TEXT_RECEIVED(from, text, time) +/// OPAQUE_RECEIVED(from, payload, time) (for signal messages or other applications) +/// +/// messages from phone to device: +/// SET_MYID(id, human readable long, human readable short) (send down the unique ID +/// string used for this node, a human readable string shown for that id, and a very +/// short human readable string suitable for oled screen) SEND_OPAQUE(dest, payload) +/// (for signal messages or other applications) SEND_TEXT(dest, text) Get all +/// nodes() (returns list of nodes, with full info, last time seen, loc, battery +/// level etc) SET_CONFIG (switches device to a new set of radio params and +/// preshared key, drops all existing nodes, force our node to rejoin this new group) +/// +/// Full information about a node on the mesh +struct NodeInfo { + // 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. + + /// + /// the node number + var num: UInt32 = 0 + + /// + /// The user info for this node + var user: User { + get {return _user ?? User()} + set {_user = newValue} + } + /// Returns true if `user` has been explicitly set. + var hasUser: Bool {return self._user != nil} + /// Clears the value of `user`. Subsequent reads from it will return its default value. + mutating func clearUser() {self._user = nil} + + /// + /// This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true. + /// Position.time now indicates the last time we received a POSITION from that node. + var position: Position { + get {return _position ?? Position()} + set {_position = newValue} + } + /// Returns true if `position` has been explicitly set. + var hasPosition: Bool {return self._position != nil} + /// Clears the value of `position`. Subsequent reads from it will return its default value. + mutating func clearPosition() {self._position = nil} + + /// + /// Returns the Signal-to-noise ratio (SNR) of the last received message, + /// as measured by the receiver. Return SNR of the last received message in dB + var snr: Float = 0 + + /// + /// Set to indicate the last time we received a packet from this node + var lastHeard: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _user: User? = nil + fileprivate var _position: Position? = nil +} + +/// +/// Unique local debugging info for this node +/// Note: we don't include position or the user info, because that will come in the +/// Sent to the phone in response to WantNodes. +struct MyNodeInfo { + // 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. + + /// + /// Tells the phone what our node number is, default starting value is + /// lowbyte of macaddr, but it will be fixed if that is already in use + var myNodeNum: UInt32 = 0 + + /// + /// Note: This flag merely means we detected a hardware GPS in our node. + /// Not the same as UserPreferences.location_sharing + var hasGps_p: Bool = false + + /// + /// # of frequencies that can be used (set at build time in the device flash image). + /// Note: this is different from max_channels, this field is telling the # of frequency bands this node can use. + /// (old name was num_channels) + var numBands: UInt32 = 0 + + /// + /// The maximum number of 'software' channels that can be set on this node. + var maxChannels: UInt32 = 0 + + /// + /// Deprecated! ONLY USED IN DEVICE CODE (for upgrading old 1.0 firmwares) DO NOT READ ELSEWHERE. + /// The region code for my radio (US, CN, etc...) + /// Note: This string is deprecated. + /// The 1.0 builds populate it based on the flashed firmware name. + /// But for newer builds this string will be unpopulated (missing/null). + /// For those builds you should instead look at the new read/write region enum in UserSettings + /// The format of this string was 1.0-US or 1.0-CN etc.. Or empty string if unset. + var region: String = String() + + /// + /// TBEAM, HELTEC, etc... + /// Starting in 1.2.11 moved to hw_model enum in the NodeInfo object. + /// Apps will still need the string here for older builds + /// (so OTA update can find the right image), but if the enum is available it will be used instead. + var hwModelDeprecated: String = String() + + /// + /// 0.0.5 etc... + var firmwareVersion: String = String() + + /// + /// An error message we'd like to report back to the mothership through analytics. + /// It indicates a serious bug occurred on the device, the device coped with it, + /// but we still want to tell the devs about the bug. + /// This field will be cleared after the phone reads MyNodeInfo + /// (i.e. it will only be reported once) + /// a numeric error code to go with error message, zero means no error + var errorCode: CriticalErrorCode = .none + + /// + /// A numeric error address (nonzero if available) + var errorAddress: UInt32 = 0 + + /// + /// The total number of errors this node has ever encountered + /// (well - since the last time we discarded preferences) + var errorCount: UInt32 = 0 + + /// + /// The total number of reboots this node has ever encountered + /// (well - since the last time we discarded preferences) + var rebootCount: UInt32 = 0 + + /// + /// How long before we consider a message abandoned and we can clear our + /// caches of any messages in flight Normally quite large to handle the worst case + /// message delivery time, 5 minutes. + /// Formerly called FLOOD_EXPIRE_TIME in the device code + var messageTimeoutMsec: UInt32 = 0 + + /// + /// The minimum app version that can talk to this device. + /// Phone/PC apps should compare this to their build number and if too low tell the user they must update their app + var minAppVersion: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// +/// Debug output from the device. +/// +/// To minimize the size of records inside the device code, if a time/source/level is not set +/// on the message it is assumed to be a continuation of the previously sent message. +/// This allows the device code to use fixed maxlen 64 byte strings for messages, +/// and then extend as needed by emitting multiple records. +struct LogRecord { + // 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. + + var message: String = String() + + /// + /// Seconds since 1970 - or 0 for unknown/unset + var time: UInt32 = 0 + + /// + /// Usually based on thread name - if known + var source: String = String() + + /// + /// Not yet set + var level: LogRecord.Level = .unset + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// + /// Log levels, chosen to match python logging conventions. + enum Level: SwiftProtobuf.Enum { + typealias RawValue = Int + case unset // = 0 + case critical // = 50 + case error // = 40 + case warning // = 30 + case info // = 20 + case debug // = 10 + case trace // = 5 + case UNRECOGNIZED(Int) + + init() { + self = .unset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 5: self = .trace + case 10: self = .debug + case 20: self = .info + case 30: self = .warning + case 40: self = .error + case 50: self = .critical + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unset: return 0 + case .trace: return 5 + case .debug: return 10 + case .info: return 20 + case .warning: return 30 + case .error: return 40 + case .critical: return 50 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension LogRecord.Level: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [LogRecord.Level] = [ + .unset, + .critical, + .error, + .warning, + .info, + .debug, + .trace, + ] +} + +#endif // swift(>=4.2) + +/// +/// Packets from the radio to the phone will appear on the fromRadio characteristic. +/// It will support READ and NOTIFY. When a new packet arrives the device will BLE notify? +/// It will sit in that descriptor until consumed by the phone, +/// at which point the next item in the FIFO will be populated. +struct FromRadio { + // 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. + + /// + /// The packet num, used to allow the phone to request missing read packets from the FIFO, + /// see our bluetooth docs + var num: UInt32 { + get {return _storage._num} + set {_uniqueStorage()._num = newValue} + } + + var payloadVariant: OneOf_PayloadVariant? { + get {return _storage._payloadVariant} + set {_uniqueStorage()._payloadVariant = newValue} + } + + var packet: MeshPacket { + get { + if case .packet(let v)? = _storage._payloadVariant {return v} + return MeshPacket() + } + set {_uniqueStorage()._payloadVariant = .packet(newValue)} + } + + /// + /// Tells the phone what our node number is, can be -1 if we've not yet joined a mesh. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + var myInfo: MyNodeInfo { + get { + if case .myInfo(let v)? = _storage._payloadVariant {return v} + return MyNodeInfo() + } + set {_uniqueStorage()._payloadVariant = .myInfo(newValue)} + } + + /// + /// One packet is sent for each node in the on radio DB + /// starts over with the first node in our DB + var nodeInfo: NodeInfo { + get { + if case .nodeInfo(let v)? = _storage._payloadVariant {return v} + return NodeInfo() + } + set {_uniqueStorage()._payloadVariant = .nodeInfo(newValue)} + } + + /// + /// set to send debug console output over our protobuf stream + var logRecord: LogRecord { + get { + if case .logRecord(let v)? = _storage._payloadVariant {return v} + return LogRecord() + } + set {_uniqueStorage()._payloadVariant = .logRecord(newValue)} + } + + /// + /// sent as true once the device has finished sending all of the responses to want_config + /// recipient should check if this ID matches our original request nonce, if + /// not, it means your config responses haven't started yet. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + var configCompleteID: UInt32 { + get { + if case .configCompleteID(let v)? = _storage._payloadVariant {return v} + return 0 + } + set {_uniqueStorage()._payloadVariant = .configCompleteID(newValue)} + } + + /// + /// Sent to tell clients the radio has just rebooted. + /// Set to true if present. + /// Not used on all transports, currently just used for the serial console. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + var rebooted: Bool { + get { + if case .rebooted(let v)? = _storage._payloadVariant {return v} + return false + } + set {_uniqueStorage()._payloadVariant = .rebooted(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum OneOf_PayloadVariant: Equatable { + case packet(MeshPacket) + /// + /// Tells the phone what our node number is, can be -1 if we've not yet joined a mesh. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + case myInfo(MyNodeInfo) + /// + /// One packet is sent for each node in the on radio DB + /// starts over with the first node in our DB + case nodeInfo(NodeInfo) + /// + /// set to send debug console output over our protobuf stream + case logRecord(LogRecord) + /// + /// sent as true once the device has finished sending all of the responses to want_config + /// recipient should check if this ID matches our original request nonce, if + /// not, it means your config responses haven't started yet. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + case configCompleteID(UInt32) + /// + /// Sent to tell clients the radio has just rebooted. + /// Set to true if present. + /// Not used on all transports, currently just used for the serial console. + /// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps. + case rebooted(Bool) + + #if !swift(>=4.1) + static func ==(lhs: FromRadio.OneOf_PayloadVariant, rhs: FromRadio.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 (.packet, .packet): return { + guard case .packet(let l) = lhs, case .packet(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.myInfo, .myInfo): return { + guard case .myInfo(let l) = lhs, case .myInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.nodeInfo, .nodeInfo): return { + guard case .nodeInfo(let l) = lhs, case .nodeInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.logRecord, .logRecord): return { + guard case .logRecord(let l) = lhs, case .logRecord(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.configCompleteID, .configCompleteID): return { + guard case .configCompleteID(let l) = lhs, case .configCompleteID(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rebooted, .rebooted): return { + guard case .rebooted(let l) = lhs, case .rebooted(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +/// +/// packets/commands to the radio will be written (reliably) to the toRadio characteristic. +/// Once the write completes the phone can assume it is handled. +struct ToRadio { + // 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. + + var payloadVariant: ToRadio.OneOf_PayloadVariant? = nil + + /// + /// send this packet on the mesh + var packet: MeshPacket { + get { + if case .packet(let v)? = payloadVariant {return v} + return MeshPacket() + } + set {payloadVariant = .packet(newValue)} + } + + /// + /// Information about the peer, sent after the phone sneds want_config_id. + /// Old clients do not send this, which is fine. + var peerInfo: ToRadio.PeerInfo { + get { + if case .peerInfo(let v)? = payloadVariant {return v} + return ToRadio.PeerInfo() + } + set {payloadVariant = .peerInfo(newValue)} + } + + /// + /// phone wants radio to send full node db to the phone, This is + /// typically the first packet sent to the radio when the phone gets a + /// bluetooth connection. The radio will respond by sending back a + /// MyNodeInfo, a owner, a radio config and a series of + /// FromRadio.node_infos, and config_complete + /// the integer you write into this field will be reported back in the + /// config_complete_id response this allows clients to never be confused by + /// a stale old partially sent config. + var wantConfigID: UInt32 { + get { + if case .wantConfigID(let v)? = payloadVariant {return v} + return 0 + } + set {payloadVariant = .wantConfigID(newValue)} + } + + /// + /// Tell API server we are disconnecting now. + /// This is useful for serial links where there is no hardware/protocol based notification that the client has dropped the link. + /// (Sending this message is optional for clients) + var disconnect: Bool { + get { + if case .disconnect(let v)? = payloadVariant {return v} + return false + } + set {payloadVariant = .disconnect(newValue)} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum OneOf_PayloadVariant: Equatable { + /// + /// send this packet on the mesh + case packet(MeshPacket) + /// + /// Information about the peer, sent after the phone sneds want_config_id. + /// Old clients do not send this, which is fine. + case peerInfo(ToRadio.PeerInfo) + /// + /// phone wants radio to send full node db to the phone, This is + /// typically the first packet sent to the radio when the phone gets a + /// bluetooth connection. The radio will respond by sending back a + /// MyNodeInfo, a owner, a radio config and a series of + /// FromRadio.node_infos, and config_complete + /// the integer you write into this field will be reported back in the + /// config_complete_id response this allows clients to never be confused by + /// a stale old partially sent config. + case wantConfigID(UInt32) + /// + /// Tell API server we are disconnecting now. + /// This is useful for serial links where there is no hardware/protocol based notification that the client has dropped the link. + /// (Sending this message is optional for clients) + case disconnect(Bool) + + #if !swift(>=4.1) + static func ==(lhs: ToRadio.OneOf_PayloadVariant, rhs: ToRadio.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 (.packet, .packet): return { + guard case .packet(let l) = lhs, case .packet(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.peerInfo, .peerInfo): return { + guard case .peerInfo(let l) = lhs, case .peerInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.wantConfigID, .wantConfigID): return { + guard case .wantConfigID(let l) = lhs, case .wantConfigID(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.disconnect, .disconnect): return { + guard case .disconnect(let l) = lhs, case .disconnect(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif + } + + /// + /// Instead of sending want_config_id as a uint32, newer clients send this structure with information about the client. + struct PeerInfo { + // 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. + + /// + /// The numeric version code for the client application, which in some cases are used to control device behavior (so the device can + /// make assumptions about who is using the API. + var appVersion: UInt32 = 0 + + /// + /// True if the peer device can gateway MQTT packets. + /// If true, the device will not try to send packets to the internet directly, + /// instead it will pass the packets to the peer for dispatching. + /// This feature is optional, if set to false the device will assume the client can not gateway to MQTT. + var mqttGateway: Bool = false + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension HardwareModel: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSET"), + 1: .same(proto: "TLORA_V2"), + 2: .same(proto: "TLORA_V1"), + 3: .same(proto: "TLORA_V2_1_1p6"), + 4: .same(proto: "TBEAM"), + 5: .same(proto: "HELTEC_V2_0"), + 6: .same(proto: "TBEAM0p7"), + 7: .same(proto: "T_ECHO"), + 8: .same(proto: "TLORA_V1_1p3"), + 9: .same(proto: "RAK4631"), + 10: .same(proto: "HELTEC_V2_1"), + 32: .same(proto: "LORA_RELAY_V1"), + 33: .same(proto: "NRF52840DK"), + 34: .same(proto: "PPR"), + 35: .same(proto: "GENIEBLOCKS"), + 36: .same(proto: "NRF52_UNKNOWN"), + 37: .same(proto: "PORTDUINO"), + 38: .same(proto: "ANDROID_SIM"), + ] +} + +extension Constants: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "Unused"), + 237: .same(proto: "DATA_PAYLOAD_LEN"), + ] +} + +extension CriticalErrorCode: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "None"), + 1: .same(proto: "TxWatchdog"), + 2: .same(proto: "SleepEnterWait"), + 3: .same(proto: "NoRadio"), + 4: .same(proto: "Unspecified"), + 5: .same(proto: "UBloxInitFailed"), + 6: .same(proto: "NoAXP192"), + 7: .same(proto: "InvalidRadioSetting"), + 8: .same(proto: "TransmitFailed"), + 9: .same(proto: "Brownout"), + 10: .same(proto: "SX1262Failure"), + 11: .same(proto: "RadioSpiBug"), + ] +} + +extension Position: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Position" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "latitude_i"), + 2: .standard(proto: "longitude_i"), + 3: .same(proto: "altitude"), + 4: .standard(proto: "battery_level"), + 9: .same(proto: "time"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularSFixed32Field(value: &self.latitudeI) }() + case 2: try { try decoder.decodeSingularSFixed32Field(value: &self.longitudeI) }() + case 3: try { try decoder.decodeSingularInt32Field(value: &self.altitude) }() + case 4: try { try decoder.decodeSingularInt32Field(value: &self.batteryLevel) }() + case 9: try { try decoder.decodeSingularFixed32Field(value: &self.time) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.latitudeI != 0 { + try visitor.visitSingularSFixed32Field(value: self.latitudeI, fieldNumber: 1) + } + if self.longitudeI != 0 { + try visitor.visitSingularSFixed32Field(value: self.longitudeI, fieldNumber: 2) + } + if self.altitude != 0 { + try visitor.visitSingularInt32Field(value: self.altitude, fieldNumber: 3) + } + if self.batteryLevel != 0 { + try visitor.visitSingularInt32Field(value: self.batteryLevel, fieldNumber: 4) + } + if self.time != 0 { + try visitor.visitSingularFixed32Field(value: self.time, fieldNumber: 9) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Position, rhs: Position) -> Bool { + if lhs.latitudeI != rhs.latitudeI {return false} + if lhs.longitudeI != rhs.longitudeI {return false} + if lhs.altitude != rhs.altitude {return false} + if lhs.batteryLevel != rhs.batteryLevel {return false} + if lhs.time != rhs.time {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "User" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .standard(proto: "long_name"), + 3: .standard(proto: "short_name"), + 4: .same(proto: "macaddr"), + 6: .standard(proto: "hw_model"), + 7: .standard(proto: "is_licensed"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularStringField(value: &self.id) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.longName) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.shortName) }() + case 4: try { try decoder.decodeSingularBytesField(value: &self.macaddr) }() + case 6: try { try decoder.decodeSingularEnumField(value: &self.hwModel) }() + case 7: try { try decoder.decodeSingularBoolField(value: &self.isLicensed) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.id.isEmpty { + try visitor.visitSingularStringField(value: self.id, fieldNumber: 1) + } + if !self.longName.isEmpty { + try visitor.visitSingularStringField(value: self.longName, fieldNumber: 2) + } + if !self.shortName.isEmpty { + try visitor.visitSingularStringField(value: self.shortName, fieldNumber: 3) + } + if !self.macaddr.isEmpty { + try visitor.visitSingularBytesField(value: self.macaddr, fieldNumber: 4) + } + if self.hwModel != .unset { + try visitor.visitSingularEnumField(value: self.hwModel, fieldNumber: 6) + } + if self.isLicensed != false { + try visitor.visitSingularBoolField(value: self.isLicensed, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: User, rhs: User) -> Bool { + if lhs.id != rhs.id {return false} + if lhs.longName != rhs.longName {return false} + if lhs.shortName != rhs.shortName {return false} + if lhs.macaddr != rhs.macaddr {return false} + if lhs.hwModel != rhs.hwModel {return false} + if lhs.isLicensed != rhs.isLicensed {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RouteDiscovery: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "RouteDiscovery" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 2: .same(proto: "route"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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 2: try { try decoder.decodeRepeatedFixed32Field(value: &self.route) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.route.isEmpty { + try visitor.visitPackedFixed32Field(value: self.route, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RouteDiscovery, rhs: RouteDiscovery) -> Bool { + if lhs.route != rhs.route {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Routing: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Routing" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "route_request"), + 2: .standard(proto: "route_reply"), + 3: .standard(proto: "error_reason"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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 { + var v: RouteDiscovery? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .routeRequest(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .routeRequest(v) + } + }() + case 2: try { + var v: RouteDiscovery? + var hadOneofValue = false + if let current = self.variant { + hadOneofValue = true + if case .routeReply(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.variant = .routeReply(v) + } + }() + case 3: try { + var v: Routing.Error? + try decoder.decodeSingularEnumField(value: &v) + if let v = v { + if self.variant != nil {try decoder.handleConflictingOneOf()} + self.variant = .errorReason(v) + } + }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // 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 self.variant { + case .routeRequest?: try { + guard case .routeRequest(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + }() + case .routeReply?: try { + guard case .routeReply(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + }() + case .errorReason?: try { + guard case .errorReason(let v)? = self.variant else { preconditionFailure() } + try visitor.visitSingularEnumField(value: v, fieldNumber: 3) + }() + case nil: break + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Routing, rhs: Routing) -> Bool { + if lhs.variant != rhs.variant {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Routing.Error: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "NONE"), + 1: .same(proto: "NO_ROUTE"), + 2: .same(proto: "GOT_NAK"), + 3: .same(proto: "TIMEOUT"), + 4: .same(proto: "NO_INTERFACE"), + 5: .same(proto: "MAX_RETRANSMIT"), + 6: .same(proto: "NO_CHANNEL"), + 7: .same(proto: "TOO_LARGE"), + 8: .same(proto: "NO_RESPONSE"), + 32: .same(proto: "BAD_REQUEST"), + 33: .same(proto: "NOT_AUTHORIZED"), + ] +} + +extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Data" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "portnum"), + 2: .same(proto: "payload"), + 3: .standard(proto: "want_response"), + 4: .same(proto: "dest"), + 5: .same(proto: "source"), + 6: .standard(proto: "request_id"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularEnumField(value: &self.portnum) }() + 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) }() + case 6: try { try decoder.decodeSingularFixed32Field(value: &self.requestID) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.portnum != .unknownApp { + try visitor.visitSingularEnumField(value: self.portnum, fieldNumber: 1) + } + if !self.payload.isEmpty { + try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 2) + } + if self.wantResponse != false { + try visitor.visitSingularBoolField(value: self.wantResponse, fieldNumber: 3) + } + if self.dest != 0 { + try visitor.visitSingularFixed32Field(value: self.dest, fieldNumber: 4) + } + if self.source != 0 { + try visitor.visitSingularFixed32Field(value: self.source, fieldNumber: 5) + } + if self.requestID != 0 { + try visitor.visitSingularFixed32Field(value: self.requestID, fieldNumber: 6) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: DataMessage, rhs: DataMessage) -> Bool { + if lhs.portnum != rhs.portnum {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} + if lhs.requestID != rhs.requestID {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension MeshPacket: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "MeshPacket" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "from"), + 2: .same(proto: "to"), + 3: .same(proto: "channel"), + 4: .same(proto: "decoded"), + 5: .same(proto: "encrypted"), + 6: .same(proto: "id"), + 7: .standard(proto: "rx_time"), + 8: .standard(proto: "rx_snr"), + 10: .standard(proto: "hop_limit"), + 11: .standard(proto: "want_ack"), + 12: .same(proto: "priority"), + 13: .standard(proto: "rx_rssi"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularFixed32Field(value: &self.from) }() + case 2: try { try decoder.decodeSingularFixed32Field(value: &self.to) }() + case 3: try { try decoder.decodeSingularUInt32Field(value: &self.channel) }() + case 4: try { + var v: DataMessage? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .decoded(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .decoded(v) + } + }() + case 5: try { + var v: Data? + try decoder.decodeSingularBytesField(value: &v) + if let v = v { + if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} + self.payloadVariant = .encrypted(v) + } + }() + case 6: try { try decoder.decodeSingularFixed32Field(value: &self.id) }() + case 7: try { try decoder.decodeSingularFixed32Field(value: &self.rxTime) }() + case 8: try { try decoder.decodeSingularFloatField(value: &self.rxSnr) }() + case 10: try { try decoder.decodeSingularUInt32Field(value: &self.hopLimit) }() + case 11: try { try decoder.decodeSingularBoolField(value: &self.wantAck) }() + case 12: try { try decoder.decodeSingularEnumField(value: &self.priority) }() + case 13: try { try decoder.decodeSingularInt32Field(value: &self.rxRssi) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.from != 0 { + try visitor.visitSingularFixed32Field(value: self.from, fieldNumber: 1) + } + if self.to != 0 { + try visitor.visitSingularFixed32Field(value: self.to, fieldNumber: 2) + } + if self.channel != 0 { + try visitor.visitSingularUInt32Field(value: self.channel, fieldNumber: 3) + } + // 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 self.payloadVariant { + case .decoded?: try { + guard case .decoded(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + }() + case .encrypted?: try { + guard case .encrypted(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularBytesField(value: v, fieldNumber: 5) + }() + case nil: break + } + if self.id != 0 { + try visitor.visitSingularFixed32Field(value: self.id, fieldNumber: 6) + } + if self.rxTime != 0 { + try visitor.visitSingularFixed32Field(value: self.rxTime, fieldNumber: 7) + } + if self.rxSnr != 0 { + try visitor.visitSingularFloatField(value: self.rxSnr, fieldNumber: 8) + } + if self.hopLimit != 0 { + try visitor.visitSingularUInt32Field(value: self.hopLimit, fieldNumber: 10) + } + if self.wantAck != false { + try visitor.visitSingularBoolField(value: self.wantAck, fieldNumber: 11) + } + if self.priority != .unset { + try visitor.visitSingularEnumField(value: self.priority, fieldNumber: 12) + } + if self.rxRssi != 0 { + try visitor.visitSingularInt32Field(value: self.rxRssi, fieldNumber: 13) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: MeshPacket, rhs: MeshPacket) -> Bool { + if lhs.from != rhs.from {return false} + if lhs.to != rhs.to {return false} + if lhs.channel != rhs.channel {return false} + if lhs.payloadVariant != rhs.payloadVariant {return false} + if lhs.id != rhs.id {return false} + if lhs.rxTime != rhs.rxTime {return false} + if lhs.rxSnr != rhs.rxSnr {return false} + if lhs.hopLimit != rhs.hopLimit {return false} + if lhs.wantAck != rhs.wantAck {return false} + if lhs.priority != rhs.priority {return false} + if lhs.rxRssi != rhs.rxRssi {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension MeshPacket.Priority: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSET"), + 1: .same(proto: "MIN"), + 10: .same(proto: "BACKGROUND"), + 64: .same(proto: "DEFAULT"), + 70: .same(proto: "RELIABLE"), + 120: .same(proto: "ACK"), + 127: .same(proto: "MAX"), + ] +} + +extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "NodeInfo" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "num"), + 2: .same(proto: "user"), + 3: .same(proto: "position"), + 7: .same(proto: "snr"), + 4: .standard(proto: "last_heard"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularUInt32Field(value: &self.num) }() + case 2: try { try decoder.decodeSingularMessageField(value: &self._user) }() + case 3: try { try decoder.decodeSingularMessageField(value: &self._position) }() + case 4: try { try decoder.decodeSingularFixed32Field(value: &self.lastHeard) }() + case 7: try { try decoder.decodeSingularFloatField(value: &self.snr) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.num != 0 { + try visitor.visitSingularUInt32Field(value: self.num, fieldNumber: 1) + } + if let v = self._user { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } + if let v = self._position { + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + } + if self.lastHeard != 0 { + try visitor.visitSingularFixed32Field(value: self.lastHeard, fieldNumber: 4) + } + if self.snr != 0 { + try visitor.visitSingularFloatField(value: self.snr, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: NodeInfo, rhs: NodeInfo) -> Bool { + if lhs.num != rhs.num {return false} + if lhs._user != rhs._user {return false} + if lhs._position != rhs._position {return false} + if lhs.snr != rhs.snr {return false} + if lhs.lastHeard != rhs.lastHeard {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "MyNodeInfo" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "my_node_num"), + 2: .standard(proto: "has_gps"), + 3: .standard(proto: "num_bands"), + 15: .standard(proto: "max_channels"), + 4: .same(proto: "region"), + 5: .standard(proto: "hw_model_deprecated"), + 6: .standard(proto: "firmware_version"), + 7: .standard(proto: "error_code"), + 8: .standard(proto: "error_address"), + 9: .standard(proto: "error_count"), + 10: .standard(proto: "reboot_count"), + 13: .standard(proto: "message_timeout_msec"), + 14: .standard(proto: "min_app_version"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularUInt32Field(value: &self.myNodeNum) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.hasGps_p) }() + case 3: try { try decoder.decodeSingularUInt32Field(value: &self.numBands) }() + case 4: try { try decoder.decodeSingularStringField(value: &self.region) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.hwModelDeprecated) }() + case 6: try { try decoder.decodeSingularStringField(value: &self.firmwareVersion) }() + case 7: try { try decoder.decodeSingularEnumField(value: &self.errorCode) }() + case 8: try { try decoder.decodeSingularUInt32Field(value: &self.errorAddress) }() + case 9: try { try decoder.decodeSingularUInt32Field(value: &self.errorCount) }() + case 10: try { try decoder.decodeSingularUInt32Field(value: &self.rebootCount) }() + case 13: try { try decoder.decodeSingularUInt32Field(value: &self.messageTimeoutMsec) }() + case 14: try { try decoder.decodeSingularUInt32Field(value: &self.minAppVersion) }() + case 15: try { try decoder.decodeSingularUInt32Field(value: &self.maxChannels) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.myNodeNum != 0 { + try visitor.visitSingularUInt32Field(value: self.myNodeNum, fieldNumber: 1) + } + if self.hasGps_p != false { + try visitor.visitSingularBoolField(value: self.hasGps_p, fieldNumber: 2) + } + if self.numBands != 0 { + try visitor.visitSingularUInt32Field(value: self.numBands, fieldNumber: 3) + } + if !self.region.isEmpty { + try visitor.visitSingularStringField(value: self.region, fieldNumber: 4) + } + if !self.hwModelDeprecated.isEmpty { + try visitor.visitSingularStringField(value: self.hwModelDeprecated, fieldNumber: 5) + } + if !self.firmwareVersion.isEmpty { + try visitor.visitSingularStringField(value: self.firmwareVersion, fieldNumber: 6) + } + if self.errorCode != .none { + try visitor.visitSingularEnumField(value: self.errorCode, fieldNumber: 7) + } + if self.errorAddress != 0 { + try visitor.visitSingularUInt32Field(value: self.errorAddress, fieldNumber: 8) + } + if self.errorCount != 0 { + try visitor.visitSingularUInt32Field(value: self.errorCount, fieldNumber: 9) + } + if self.rebootCount != 0 { + try visitor.visitSingularUInt32Field(value: self.rebootCount, fieldNumber: 10) + } + if self.messageTimeoutMsec != 0 { + try visitor.visitSingularUInt32Field(value: self.messageTimeoutMsec, fieldNumber: 13) + } + if self.minAppVersion != 0 { + try visitor.visitSingularUInt32Field(value: self.minAppVersion, fieldNumber: 14) + } + if self.maxChannels != 0 { + try visitor.visitSingularUInt32Field(value: self.maxChannels, fieldNumber: 15) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: MyNodeInfo, rhs: MyNodeInfo) -> Bool { + if lhs.myNodeNum != rhs.myNodeNum {return false} + if lhs.hasGps_p != rhs.hasGps_p {return false} + if lhs.numBands != rhs.numBands {return false} + if lhs.maxChannels != rhs.maxChannels {return false} + if lhs.region != rhs.region {return false} + if lhs.hwModelDeprecated != rhs.hwModelDeprecated {return false} + if lhs.firmwareVersion != rhs.firmwareVersion {return false} + if lhs.errorCode != rhs.errorCode {return false} + if lhs.errorAddress != rhs.errorAddress {return false} + if lhs.errorCount != rhs.errorCount {return false} + if lhs.rebootCount != rhs.rebootCount {return false} + if lhs.messageTimeoutMsec != rhs.messageTimeoutMsec {return false} + if lhs.minAppVersion != rhs.minAppVersion {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension LogRecord: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "LogRecord" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "message"), + 2: .same(proto: "time"), + 3: .same(proto: "source"), + 4: .same(proto: "level"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularStringField(value: &self.message) }() + case 2: try { try decoder.decodeSingularFixed32Field(value: &self.time) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.source) }() + case 4: try { try decoder.decodeSingularEnumField(value: &self.level) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.message.isEmpty { + try visitor.visitSingularStringField(value: self.message, fieldNumber: 1) + } + if self.time != 0 { + try visitor.visitSingularFixed32Field(value: self.time, fieldNumber: 2) + } + if !self.source.isEmpty { + try visitor.visitSingularStringField(value: self.source, fieldNumber: 3) + } + if self.level != .unset { + try visitor.visitSingularEnumField(value: self.level, fieldNumber: 4) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: LogRecord, rhs: LogRecord) -> Bool { + if lhs.message != rhs.message {return false} + if lhs.time != rhs.time {return false} + if lhs.source != rhs.source {return false} + if lhs.level != rhs.level {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension LogRecord.Level: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSET"), + 5: .same(proto: "TRACE"), + 10: .same(proto: "DEBUG"), + 20: .same(proto: "INFO"), + 30: .same(proto: "WARNING"), + 40: .same(proto: "ERROR"), + 50: .same(proto: "CRITICAL"), + ] +} + +extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "FromRadio" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "num"), + 11: .same(proto: "packet"), + 3: .standard(proto: "my_info"), + 4: .standard(proto: "node_info"), + 7: .standard(proto: "log_record"), + 8: .standard(proto: "config_complete_id"), + 9: .same(proto: "rebooted"), + ] + + fileprivate class _StorageClass { + var _num: UInt32 = 0 + var _payloadVariant: FromRadio.OneOf_PayloadVariant? + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _num = source._num + _payloadVariant = source._payloadVariant + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(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.decodeSingularUInt32Field(value: &_storage._num) }() + case 3: try { + var v: MyNodeInfo? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .myInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .myInfo(v) + } + }() + case 4: try { + var v: NodeInfo? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .nodeInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .nodeInfo(v) + } + }() + case 7: try { + var v: LogRecord? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .logRecord(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .logRecord(v) + } + }() + case 8: try { + var v: UInt32? + try decoder.decodeSingularUInt32Field(value: &v) + if let v = v { + if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .configCompleteID(v) + } + }() + case 9: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .rebooted(v) + } + }() + case 11: try { + var v: MeshPacket? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .packet(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .packet(v) + } + }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if _storage._num != 0 { + try visitor.visitSingularUInt32Field(value: _storage._num, fieldNumber: 1) + } + // 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 _storage._payloadVariant { + case .myInfo?: try { + guard case .myInfo(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + }() + case .nodeInfo?: try { + guard case .nodeInfo(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + }() + case .logRecord?: try { + guard case .logRecord(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + }() + case .configCompleteID?: try { + guard case .configCompleteID(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 8) + }() + case .rebooted?: try { + guard case .rebooted(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 9) + }() + case .packet?: try { + guard case .packet(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 11) + }() + case nil: break + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: FromRadio, rhs: FromRadio) -> 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._num != rhs_storage._num {return false} + if _storage._payloadVariant != rhs_storage._payloadVariant {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ToRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ToRadio" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 2: .same(proto: "packet"), + 3: .standard(proto: "peer_info"), + 100: .standard(proto: "want_config_id"), + 104: .same(proto: "disconnect"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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 2: try { + var v: MeshPacket? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .packet(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .packet(v) + } + }() + case 3: try { + var v: ToRadio.PeerInfo? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .peerInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .peerInfo(v) + } + }() + case 100: try { + var v: UInt32? + try decoder.decodeSingularUInt32Field(value: &v) + if let v = v { + if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} + self.payloadVariant = .wantConfigID(v) + } + }() + case 104: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} + self.payloadVariant = .disconnect(v) + } + }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // 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 self.payloadVariant { + case .packet?: try { + guard case .packet(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + }() + case .peerInfo?: try { + guard case .peerInfo(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) + }() + case .wantConfigID?: try { + guard case .wantConfigID(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 100) + }() + case .disconnect?: try { + guard case .disconnect(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 104) + }() + case nil: break + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ToRadio, rhs: ToRadio) -> Bool { + if lhs.payloadVariant != rhs.payloadVariant {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ToRadio.PeerInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = ToRadio.protoMessageName + ".PeerInfo" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "app_version"), + 2: .standard(proto: "mqtt_gateway"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularUInt32Field(value: &self.appVersion) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.mqttGateway) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.appVersion != 0 { + try visitor.visitSingularUInt32Field(value: self.appVersion, fieldNumber: 1) + } + if self.mqttGateway != false { + try visitor.visitSingularBoolField(value: self.mqttGateway, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ToRadio.PeerInfo, rhs: ToRadio.PeerInfo) -> Bool { + if lhs.appVersion != rhs.appVersion {return false} + if lhs.mqttGateway != rhs.mqttGateway {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticClient/Protobufs/mqtt.pb.swift b/MeshtasticClient/Protobufs/mqtt.pb.swift new file mode 100644 index 00000000..f4870c0b --- /dev/null +++ b/MeshtasticClient/Protobufs/mqtt.pb.swift @@ -0,0 +1,144 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: mqtt.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// This message wraps a MeshPacket with extra metadata about the sender and how it arrived. +struct ServiceEnvelope { + // 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. + + /// + /// The (probably encrypted) packet + var packet: MeshPacket { + get {return _storage._packet ?? MeshPacket()} + set {_uniqueStorage()._packet = newValue} + } + /// Returns true if `packet` has been explicitly set. + var hasPacket: Bool {return _storage._packet != nil} + /// Clears the value of `packet`. Subsequent reads from it will return its default value. + mutating func clearPacket() {_uniqueStorage()._packet = nil} + + /// + /// The global channel ID it was sent on + var channelID: String { + get {return _storage._channelID} + set {_uniqueStorage()._channelID = newValue} + } + + /// + /// The sending gateway node ID. Can we use this to authenticate/prevent fake + /// nodeid impersonation for senders? - i.e. use gateway/mesh id (which is authenticated) + local node id as + /// the globally trusted nodenum + var gatewayID: String { + get {return _storage._gatewayID} + set {_uniqueStorage()._gatewayID = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension ServiceEnvelope: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ServiceEnvelope" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "packet"), + 2: .standard(proto: "channel_id"), + 3: .standard(proto: "gateway_id"), + ] + + fileprivate class _StorageClass { + var _packet: MeshPacket? = nil + var _channelID: String = String() + var _gatewayID: String = String() + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _packet = source._packet + _channelID = source._channelID + _gatewayID = source._gatewayID + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(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._packet) }() + case 2: try { try decoder.decodeSingularStringField(value: &_storage._channelID) }() + case 3: try { try decoder.decodeSingularStringField(value: &_storage._gatewayID) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if let v = _storage._packet { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if !_storage._channelID.isEmpty { + try visitor.visitSingularStringField(value: _storage._channelID, fieldNumber: 2) + } + if !_storage._gatewayID.isEmpty { + try visitor.visitSingularStringField(value: _storage._gatewayID, fieldNumber: 3) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ServiceEnvelope, rhs: ServiceEnvelope) -> 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._packet != rhs_storage._packet {return false} + if _storage._channelID != rhs_storage._channelID {return false} + if _storage._gatewayID != rhs_storage._gatewayID {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticClient/Protobufs/portnums.pb.swift b/MeshtasticClient/Protobufs/portnums.pb.swift new file mode 100644 index 00000000..d168ec01 --- /dev/null +++ b/MeshtasticClient/Protobufs/portnums.pb.swift @@ -0,0 +1,227 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: portnums.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// For any new 'apps' that run on the device or via sister apps on phones/PCs they should pick and use a +/// unique 'portnum' for their application. +/// +/// If you are making a new app using meshtastic, please send in a pull request to add your 'portnum' to this +/// master table. +/// PortNums should be assigned in the following range: +/// +/// 0-63 Core Meshtastic use, do not use for third party apps +/// 64-127 Registered 3rd party apps, send in a pull request that adds a new entry to portnums.proto to register your application +/// 256-511 Use one of these portnums for your private applications that you don't want to register publically +/// +/// All other values are reserved. +/// +/// Note: This was formerly a Type enum named 'typ' with the same id # +/// +/// We have change to this 'portnum' based scheme for specifying app handlers for particular payloads. +/// This change is backwards compatible by treating the legacy OPAQUE/CLEAR_TEXT values identically. +enum PortNum: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// Deprecated: do not use in new code (formerly called OPAQUE) + /// A message sent from a device outside of the mesh, in a form the mesh does not understand + /// NOTE: This must be 0, because it is documented in IMeshService.aidl to be so + case unknownApp // = 0 + + /// + /// A simple UTF-8 text message, which even the little micros in the mesh + /// can understand and show on their screen eventually in some circumstances + /// even signal might send messages in this form (see below) + /// Formerly called CLEAR_TEXT + case textMessageApp // = 1 + + /// + /// Reserved for built-in GPIO/example app. + /// See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number + case remoteHardwareApp // = 2 + + /// + /// The built-in position messaging app. + /// Payload is a [Position](/developers/protobufs/api.md#position) message + case positionApp // = 3 + + /// + /// The built-in user info app. + /// Payload is a [User](/developers/protobufs/api.md#user) message + case nodeinfoApp // = 4 + + /// + /// Protocol control packets for mesh protocol use. + /// Payload is a [Routing](/developers/protobufs/api.md#routing) message + case routingApp // = 5 + + /// + /// Admin control packets. + /// Payload is a [AdminMessage](/developers/protobufs/api.md#adminmessage) message + case adminApp // = 6 + + /// + /// Provides a 'ping' service that replies to any packet it receives. + /// Also serves as a small example plugin. + case replyApp // = 32 + + /// + /// Used for the python IP tunnel feature + case ipTunnelApp // = 33 + + /// + /// Provides a hardware serial interface to send and receive from the Meshtastic network. + /// Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic + /// network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. + /// Maximum packet size of 240 bytes. + /// Plugin is disabled by default can be turned on by setting SERIALPLUGIN_ENABLED = 1 in SerialPlugh.cpp. + /// Maintained by Jm Casler (MC Hamster) : jm@casler.org + case serialApp // = 64 + + /// + /// STORE_FORWARD_APP (Work in Progress) + /// Maintained by Jm Casler (MC Hamster) : jm@casler.org + case storeForwardApp // = 65 + + /// + /// STORE_FORWARD_APP (Work in Progress) + /// Maintained by Jm Casler (MC Hamster) : jm@casler.org + case rangeTestApp // = 66 + + /// + /// Provides a format to send and receive environmental data from the Meshtastic network. + /// Maintained by Charles Crossan (crossan007) : crossan007@gmail.com + case environmentalMeasurementApp // = 67 + + /// + /// Private applications should use portnums >= 256. + /// To simplify initial development and testing you can use "PRIVATE_APP" + /// in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/Meshtastic-device/blob/master/bin/regen-protos.sh)) + case privateApp // = 256 + + /// + /// ATAK Forwarder Plugin https://github.com/paulmandal/atak-forwarder + case atakForwarder // = 257 + + /// + /// Currently we limit port nums to no higher than this value + case max // = 511 + case UNRECOGNIZED(Int) + + init() { + self = .unknownApp + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unknownApp + case 1: self = .textMessageApp + case 2: self = .remoteHardwareApp + case 3: self = .positionApp + case 4: self = .nodeinfoApp + case 5: self = .routingApp + case 6: self = .adminApp + case 32: self = .replyApp + case 33: self = .ipTunnelApp + case 64: self = .serialApp + case 65: self = .storeForwardApp + case 66: self = .rangeTestApp + case 67: self = .environmentalMeasurementApp + case 256: self = .privateApp + case 257: self = .atakForwarder + case 511: self = .max + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unknownApp: return 0 + case .textMessageApp: return 1 + case .remoteHardwareApp: return 2 + case .positionApp: return 3 + case .nodeinfoApp: return 4 + case .routingApp: return 5 + case .adminApp: return 6 + case .replyApp: return 32 + case .ipTunnelApp: return 33 + case .serialApp: return 64 + case .storeForwardApp: return 65 + case .rangeTestApp: return 66 + case .environmentalMeasurementApp: return 67 + case .privateApp: return 256 + case .atakForwarder: return 257 + case .max: return 511 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension PortNum: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [PortNum] = [ + .unknownApp, + .textMessageApp, + .remoteHardwareApp, + .positionApp, + .nodeinfoApp, + .routingApp, + .adminApp, + .replyApp, + .ipTunnelApp, + .serialApp, + .storeForwardApp, + .rangeTestApp, + .environmentalMeasurementApp, + .privateApp, + .atakForwarder, + .max, + ] +} + +#endif // swift(>=4.2) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension PortNum: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNKNOWN_APP"), + 1: .same(proto: "TEXT_MESSAGE_APP"), + 2: .same(proto: "REMOTE_HARDWARE_APP"), + 3: .same(proto: "POSITION_APP"), + 4: .same(proto: "NODEINFO_APP"), + 5: .same(proto: "ROUTING_APP"), + 6: .same(proto: "ADMIN_APP"), + 32: .same(proto: "REPLY_APP"), + 33: .same(proto: "IP_TUNNEL_APP"), + 64: .same(proto: "SERIAL_APP"), + 65: .same(proto: "STORE_FORWARD_APP"), + 66: .same(proto: "RANGE_TEST_APP"), + 67: .same(proto: "ENVIRONMENTAL_MEASUREMENT_APP"), + 256: .same(proto: "PRIVATE_APP"), + 257: .same(proto: "ATAK_FORWARDER"), + 511: .same(proto: "MAX"), + ] +} diff --git a/MeshtasticClient/Protobufs/radioconfig.pb.swift b/MeshtasticClient/Protobufs/radioconfig.pb.swift new file mode 100644 index 00000000..d037e53b --- /dev/null +++ b/MeshtasticClient/Protobufs/radioconfig.pb.swift @@ -0,0 +1,1534 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: radioconfig.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +/// +/// Meshtastic protobufs +/// +/// For more information on protobufs (and tools to use them with the language of your choice) see +/// https://developers.google.com/protocol-buffers/docs/proto3 +/// +/// We are not placing any of these defs inside a package, because if you do the +/// resulting nanopb version is super verbose package mesh. +/// +/// Protobuf build instructions: +/// +/// To build java classes for reading writing: +/// protoc -I=. --java_out /tmp mesh.proto +/// +/// To generate Nanopb c code: +/// /home/kevinh/packages/nanopb-0.4.0-linux-x86/generator-bin/protoc --nanopb_out=/tmp -I=app/src/main/proto mesh.proto +/// +/// Nanopb binaries available here: https://jpa.kapsi.fi/nanopb/download/ use nanopb 0.4.0 + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// The frequency/regulatory region the user has selected. +/// +/// Note: In 1.0 builds (which must still be supported by the android app for a +/// long time) this field will be unpopulated. +/// +/// If firmware is ever upgraded from an old 1.0ish build, the old +/// MyNodeInfo.region string will be used to set UserPreferences.region and the +/// old value will be no longer set. +enum RegionCode: SwiftProtobuf.Enum { + typealias RawValue = Int + case unset // = 0 + case us // = 1 + case eu433 // = 2 + case eu865 // = 3 + case cn // = 4 + case jp // = 5 + case anz // = 6 + case kr // = 7 + case tw // = 8 + case ru // = 9 + case UNRECOGNIZED(Int) + + init() { + self = .unset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 1: self = .us + case 2: self = .eu433 + case 3: self = .eu865 + case 4: self = .cn + case 5: self = .jp + case 6: self = .anz + case 7: self = .kr + case 8: self = .tw + case 9: self = .ru + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unset: return 0 + case .us: return 1 + case .eu433: return 2 + case .eu865: return 3 + case .cn: return 4 + case .jp: return 5 + case .anz: return 6 + case .kr: return 7 + case .tw: return 8 + case .ru: return 9 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension RegionCode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [RegionCode] = [ + .unset, + .us, + .eu433, + .eu865, + .cn, + .jp, + .anz, + .kr, + .tw, + .ru, + ] +} + +#endif // swift(>=4.2) + +/// +/// Sets the charge control current of devices with a battery charger that can be +/// configured. This is passed into the axp power management chip like on the tbeam. +enum ChargeCurrent: SwiftProtobuf.Enum { + typealias RawValue = Int + case maunset // = 0 + case ma100 // = 1 + case ma190 // = 2 + case ma280 // = 3 + case ma360 // = 4 + case ma450 // = 5 + case ma550 // = 6 + case ma630 // = 7 + case ma700 // = 8 + case ma780 // = 9 + case ma880 // = 10 + case ma960 // = 11 + case ma1000 // = 12 + case ma1080 // = 13 + case ma1160 // = 14 + case ma1240 // = 15 + case ma1320 // = 16 + case UNRECOGNIZED(Int) + + init() { + self = .maunset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .maunset + case 1: self = .ma100 + case 2: self = .ma190 + case 3: self = .ma280 + case 4: self = .ma360 + case 5: self = .ma450 + case 6: self = .ma550 + case 7: self = .ma630 + case 8: self = .ma700 + case 9: self = .ma780 + case 10: self = .ma880 + case 11: self = .ma960 + case 12: self = .ma1000 + case 13: self = .ma1080 + case 14: self = .ma1160 + case 15: self = .ma1240 + case 16: self = .ma1320 + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .maunset: return 0 + case .ma100: return 1 + case .ma190: return 2 + case .ma280: return 3 + case .ma360: return 4 + case .ma450: return 5 + case .ma550: return 6 + case .ma630: return 7 + case .ma700: return 8 + case .ma780: return 9 + case .ma880: return 10 + case .ma960: return 11 + case .ma1000: return 12 + case .ma1080: return 13 + case .ma1160: return 14 + case .ma1240: return 15 + case .ma1320: return 16 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension ChargeCurrent: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [ChargeCurrent] = [ + .maunset, + .ma100, + .ma190, + .ma280, + .ma360, + .ma450, + .ma550, + .ma630, + .ma700, + .ma780, + .ma880, + .ma960, + .ma1000, + .ma1080, + .ma1160, + .ma1240, + .ma1320, + ] +} + +#endif // swift(>=4.2) + +/// +/// How the GPS hardware in this unit is operated. +/// Note: This is independent of how our location is shared with other devices. +/// For that see LocationSharing +enum GpsOperation: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// This is treated as GpsOpMobile - it is the default setting + case gpsOpUnset // = 0 + + /// + /// Note: This mode was removed, because it is identical go GpsOpMobile with a gps_update_rate of once per day + /// This node is mostly stationary, we should try to get location only once per day, + /// Once we have that position we should turn the GPS to sleep mode + /// This is the recommended configuration for stationary 'router' nodes + case gpsOpStationary // = 1 + + /// + /// This node is mobile and we should get GPS position at a rate governed by gps_update_rate + case gpsOpMobile // = 2 + + /// + /// We should only use the GPS to get time (no location data should be acquired/stored) + /// Once we have the time we treat gps_update_interval as MAXINT (i.e. sleep forever) + case gpsOpTimeOnly // = 3 + + /// + /// GPS is always turned off - this mode is not recommended - use GpsOpTimeOnly instead + case gpsOpDisabled // = 4 + case UNRECOGNIZED(Int) + + init() { + self = .gpsOpUnset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .gpsOpUnset + case 1: self = .gpsOpStationary + case 2: self = .gpsOpMobile + case 3: self = .gpsOpTimeOnly + case 4: self = .gpsOpDisabled + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .gpsOpUnset: return 0 + case .gpsOpStationary: return 1 + case .gpsOpMobile: return 2 + case .gpsOpTimeOnly: return 3 + case .gpsOpDisabled: return 4 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension GpsOperation: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [GpsOperation] = [ + .gpsOpUnset, + .gpsOpStationary, + .gpsOpMobile, + .gpsOpTimeOnly, + .gpsOpDisabled, + ] +} + +#endif // swift(>=4.2) + +/// +/// How the GPS coordinates are displayed on the OLED screen. +enum GpsCoordinateFormat: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// GPS coordinates are displayed in the normal decimal degrees format: + /// DD.DDDDDD DDD.DDDDDD + case gpsFormatDec // = 0 + + /// + /// GPS coordinates are displayed in the degrees minutes seconds format: + /// DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant + case gpsFormatDms // = 1 + + /// + /// GPS coordinates are displayed in Universal Transverse Mercator format: + /// ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing + case gpsFormatUtm // = 2 + + /// + /// GPS coordinates are displayed in Military Grid Reference System format: + /// ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, + /// E is easting, N is northing + case gpsFormatMgrs // = 3 + + /// + /// GPS coordinates are displayed in Open Location Code (aka Plus Codes). + case gpsFormatOlc // = 4 + + /// + /// GPS coordinates are displayed in Ordnance Survey Grid Reference (the National Grid System of the UK). + /// Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, E is the easting, + /// N is the northing + case gpsFormatOsgr // = 5 + case UNRECOGNIZED(Int) + + init() { + self = .gpsFormatDec + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .gpsFormatDec + case 1: self = .gpsFormatDms + case 2: self = .gpsFormatUtm + case 3: self = .gpsFormatMgrs + case 4: self = .gpsFormatOlc + case 5: self = .gpsFormatOsgr + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .gpsFormatDec: return 0 + case .gpsFormatDms: return 1 + case .gpsFormatUtm: return 2 + case .gpsFormatMgrs: return 3 + case .gpsFormatOlc: return 4 + case .gpsFormatOsgr: return 5 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension GpsCoordinateFormat: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [GpsCoordinateFormat] = [ + .gpsFormatDec, + .gpsFormatDms, + .gpsFormatUtm, + .gpsFormatMgrs, + .gpsFormatOlc, + .gpsFormatOsgr, + ] +} + +#endif // swift(>=4.2) + +/// +/// How our location is shared with other nodes (or the local phone) +enum LocationSharing: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// This is the default and treated as LocEnabled. + case locUnset // = 0 + + /// + /// We are sharing our location + case locEnabled // = 1 + + /// + /// We are not sharing our location (if the unit has a GPS it will default to only get time - i.e. GpsOpTimeOnly) + case locDisabled // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .locUnset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .locUnset + case 1: self = .locEnabled + case 2: self = .locDisabled + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .locUnset: return 0 + case .locEnabled: return 1 + case .locDisabled: return 2 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension LocationSharing: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [LocationSharing] = [ + .locUnset, + .locEnabled, + .locDisabled, + ] +} + +#endif // swift(>=4.2) + +/// +/// The entire set of user settable/readable settings for our radio device. +/// Includes both the current channel settings and any preferences the user has +/// set for behavior of their node +struct RadioConfig { + // 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. + + var preferences: RadioConfig.UserPreferences { + get {return _preferences ?? RadioConfig.UserPreferences()} + set {_preferences = newValue} + } + /// Returns true if `preferences` has been explicitly set. + var hasPreferences: Bool {return self._preferences != nil} + /// Clears the value of `preferences`. Subsequent reads from it will return its default value. + mutating func clearPreferences() {self._preferences = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + /// + /// see [software design](/software/other/sw-design.md) for more information on these preferences + struct UserPreferences { + // 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. + + /// + /// We should send our position this often (but only if it has changed significantly) + /// Defaults to 15 minutes + var positionBroadcastSecs: UInt32 { + get {return _storage._positionBroadcastSecs} + set {_uniqueStorage()._positionBroadcastSecs = newValue} + } + + /// + /// Send our owner info at least this often (also we always send once at boot - to rejoin the mesh) + var sendOwnerInterval: UInt32 { + get {return _storage._sendOwnerInterval} + set {_uniqueStorage()._sendOwnerInterval = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of 1 minute + var waitBluetoothSecs: UInt32 { + get {return _storage._waitBluetoothSecs} + set {_uniqueStorage()._waitBluetoothSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of one minute + var screenOnSecs: UInt32 { + get {return _storage._screenOnSecs} + set {_uniqueStorage()._screenOnSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of 15 minutes + /// IMPORTANT NOTE FOR DEVICE CLIENTS: YOU MUST SEND SOME SORT OF PACKET TO THE PHONE AT LEAST THIS OFTEN OR THE DEVICE WILL DECIDE YOU ARE GONE! + var phoneTimeoutSecs: UInt32 { + get {return _storage._phoneTimeoutSecs} + set {_uniqueStorage()._phoneTimeoutSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of two hours, MAXUINT for disabled + var phoneSdsTimeoutSec: UInt32 { + get {return _storage._phoneSdsTimeoutSec} + set {_uniqueStorage()._phoneSdsTimeoutSec = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of two hours, MAXUINT for disabled + var meshSdsTimeoutSecs: UInt32 { + get {return _storage._meshSdsTimeoutSecs} + set {_uniqueStorage()._meshSdsTimeoutSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of one year + var sdsSecs: UInt32 { + get {return _storage._sdsSecs} + set {_uniqueStorage()._sdsSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of 3600 + var lsSecs: UInt32 { + get {return _storage._lsSecs} + set {_uniqueStorage()._lsSecs = newValue} + } + + /// + /// Power management state machine option. + /// See [power management](/software/other/power.md) for details. + /// 0 for default of 10 seconds + var minWakeSecs: UInt32 { + get {return _storage._minWakeSecs} + set {_uniqueStorage()._minWakeSecs = newValue} + } + + /// + /// If set, this node will try to join the specified wifi network and + /// acquire an address via DHCP + var wifiSsid: String { + get {return _storage._wifiSsid} + set {_uniqueStorage()._wifiSsid = newValue} + } + + /// + /// If set, will be use to authenticate to the named wifi + var wifiPassword: String { + get {return _storage._wifiPassword} + set {_uniqueStorage()._wifiPassword = newValue} + } + + /// + /// If set, the node will operate as an AP (and DHCP server), otherwise it + /// will be a station + var wifiApMode: Bool { + get {return _storage._wifiApMode} + set {_uniqueStorage()._wifiApMode = newValue} + } + + /// + /// The region code for my radio (US, CN, EU433, etc...) + var region: RegionCode { + get {return _storage._region} + set {_uniqueStorage()._region = newValue} + } + + /// + /// Sets the current of the battery charger + var chargeCurrent: ChargeCurrent { + get {return _storage._chargeCurrent} + set {_uniqueStorage()._chargeCurrent = newValue} + } + + /// + /// Are we operating as a router. + /// Changes behavior in the following ways: + /// The device will only sleep for critically low battery level (i.e. always tries to stay alive for the mesh) + /// In the future routing decisions will preferentially route packets through nodes with this attribute (because assumed + /// good line of sight) + var isRouter: Bool { + get {return _storage._isRouter} + set {_uniqueStorage()._isRouter = newValue} + } + + /// + /// If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in + /// we should try to minimize power consumption as much as possible. + /// YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case). + var isLowPower: Bool { + get {return _storage._isLowPower} + set {_uniqueStorage()._isLowPower = newValue} + } + + /// + /// If set, this node is at a fixed position. + /// We will generate GPS position updates at the regular interval, but use whatever the last lat/lon/alt we have for the node. + /// The lat/lon/alt can be set by an internal GPS or with the help of the app. + var fixedPosition: Bool { + get {return _storage._fixedPosition} + set {_uniqueStorage()._fixedPosition = newValue} + } + + /// + /// If set, this will disable the SerialConsole by not initilizing the StreamAPI + var serialDisabled: Bool { + get {return _storage._serialDisabled} + set {_uniqueStorage()._serialDisabled = newValue} + } + + /// + /// How our location is shared with other nodes (or the local phone) + var locationShare: LocationSharing { + get {return _storage._locationShare} + set {_uniqueStorage()._locationShare = newValue} + } + + /// + /// How the GPS hardware in this unit is operated. + /// Note: This is independent of how our location is shared with other devices. + /// For that see LocationSharing + var gpsOperation: GpsOperation { + get {return _storage._gpsOperation} + set {_uniqueStorage()._gpsOperation = newValue} + } + + /// + /// How often should we try to get GPS position (in seconds) when we are in GpsOpMobile mode? + /// or zero for the default of once every 30 seconds + /// or a very large value (maxint) to update only once at boot. + var gpsUpdateInterval: UInt32 { + get {return _storage._gpsUpdateInterval} + set {_uniqueStorage()._gpsUpdateInterval = newValue} + } + + /// + /// How long should we try to get our position during each gps_update_interval attempt? (in seconds) + /// Or if zero, use the default of 30 seconds. + /// If we don't get a new gps fix in that time, the gps will be put into sleep until the next gps_update_rate + /// window. + var gpsAttemptTime: UInt32 { + get {return _storage._gpsAttemptTime} + set {_uniqueStorage()._gpsAttemptTime = newValue} + } + + /// + /// This parameter is for advanced users with advanced test equipment, we do not recommend most users use it. + /// A frequency offset that is added to to the calculated band center frequency. + /// Used to correct for crystal calibration errors. + var frequencyOffset: Float { + get {return _storage._frequencyOffset} + set {_uniqueStorage()._frequencyOffset = newValue} + } + + /// + /// The server to use for our MQTT global message gateway feature. + /// If not set, the default server will be used + var mqttServer: String { + get {return _storage._mqttServer} + set {_uniqueStorage()._mqttServer = newValue} + } + + /// + /// If a meshtastic node is able to reach the internet it will normally attempt to gateway any channels that are marked as + /// is_uplink_enabled or is_downlink_enabled. + /// But if this flag is set, all MQTT features will be disabled and no servers will be contacted. + var mqttDisabled: Bool { + get {return _storage._mqttDisabled} + set {_uniqueStorage()._mqttDisabled = newValue} + } + + /// + /// How the GPS coordinates are displayed on the OLED screen. + var gpsFormat: GpsCoordinateFormat { + get {return _storage._gpsFormat} + set {_uniqueStorage()._gpsFormat = newValue} + } + + /// + /// This setting is never saved to disk, but if set, all device settings will be returned to factory defaults. + /// (Region, serial number etc... will be preserved) + var factoryReset: Bool { + get {return _storage._factoryReset} + set {_uniqueStorage()._factoryReset = newValue} + } + + /// + /// By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). + /// Set this to true to leave the debug log outputting even when API is active. + var debugLogEnabled: Bool { + get {return _storage._debugLogEnabled} + set {_uniqueStorage()._debugLogEnabled = newValue} + } + + /// + /// If true, radio should not try to be smart about what packets to queue to + /// the phone + /// bool keep_all_packets = 101; + /// If true, we will try to capture all the packets sent on the mesh, not just the ones destined to our node. + /// bool promiscuous_mode = 102; + /// For testing it is useful sometimes to force a node to never listen to + /// particular other nodes (simulating radio out of range). All nodenums listed + /// in ignore_incoming will have packets they send droped on receive (by router.cpp) + var ignoreIncoming: [UInt32] { + get {return _storage._ignoreIncoming} + set {_uniqueStorage()._ignoreIncoming = newValue} + } + + /// + /// Preferences for the SerialPlugin + /// FIXME - Move this out of UserPreferences and into a section for plugin configuration. + var serialpluginEnabled: Bool { + get {return _storage._serialpluginEnabled} + set {_uniqueStorage()._serialpluginEnabled = newValue} + } + + var serialpluginEcho: Bool { + get {return _storage._serialpluginEcho} + set {_uniqueStorage()._serialpluginEcho = newValue} + } + + var serialpluginRxd: UInt32 { + get {return _storage._serialpluginRxd} + set {_uniqueStorage()._serialpluginRxd = newValue} + } + + var serialpluginTxd: UInt32 { + get {return _storage._serialpluginTxd} + set {_uniqueStorage()._serialpluginTxd = newValue} + } + + var serialpluginTimeout: UInt32 { + get {return _storage._serialpluginTimeout} + set {_uniqueStorage()._serialpluginTimeout = newValue} + } + + var serialpluginMode: UInt32 { + get {return _storage._serialpluginMode} + set {_uniqueStorage()._serialpluginMode = newValue} + } + + /// + /// Preferences for the ExternalNotificationPlugin + /// FIXME - Move this out of UserPreferences and into a section for plugin configuration. + var extNotificationPluginEnabled: Bool { + get {return _storage._extNotificationPluginEnabled} + set {_uniqueStorage()._extNotificationPluginEnabled = newValue} + } + + var extNotificationPluginOutputMs: UInt32 { + get {return _storage._extNotificationPluginOutputMs} + set {_uniqueStorage()._extNotificationPluginOutputMs = newValue} + } + + var extNotificationPluginOutput: UInt32 { + get {return _storage._extNotificationPluginOutput} + set {_uniqueStorage()._extNotificationPluginOutput = newValue} + } + + var extNotificationPluginActive: Bool { + get {return _storage._extNotificationPluginActive} + set {_uniqueStorage()._extNotificationPluginActive = newValue} + } + + var extNotificationPluginAlertMessage: Bool { + get {return _storage._extNotificationPluginAlertMessage} + set {_uniqueStorage()._extNotificationPluginAlertMessage = newValue} + } + + var extNotificationPluginAlertBell: Bool { + get {return _storage._extNotificationPluginAlertBell} + set {_uniqueStorage()._extNotificationPluginAlertBell = newValue} + } + + /// + ///Preferences for the RangeTestPlugin + /// FIXME - Move this out of UserPreferences and into a section for plugin configuration. + var rangeTestPluginEnabled: Bool { + get {return _storage._rangeTestPluginEnabled} + set {_uniqueStorage()._rangeTestPluginEnabled = newValue} + } + + var rangeTestPluginSender: UInt32 { + get {return _storage._rangeTestPluginSender} + set {_uniqueStorage()._rangeTestPluginSender = newValue} + } + + var rangeTestPluginSave: Bool { + get {return _storage._rangeTestPluginSave} + set {_uniqueStorage()._rangeTestPluginSave = newValue} + } + + /// + /// Preferences for the StoreForwardPlugin + ///FIXME - Move this out of UserPreferences and into a section for plugin configuration. (was 136) + var storeForwardPluginEnabled: Bool { + get {return _storage._storeForwardPluginEnabled} + set {_uniqueStorage()._storeForwardPluginEnabled = newValue} + } + + var storeForwardPluginRecords: UInt32 { + get {return _storage._storeForwardPluginRecords} + set {_uniqueStorage()._storeForwardPluginRecords = newValue} + } + + /// + /// Preferences for the EnvironmentalMeasurement Plugin + /// FIXME - Move this out of UserPreferences and into a section for plugin configuration. + /// Enable/Disable the environmental measurement plugin measurement collection + var environmentalMeasurementPluginMeasurementEnabled: Bool { + get {return _storage._environmentalMeasurementPluginMeasurementEnabled} + set {_uniqueStorage()._environmentalMeasurementPluginMeasurementEnabled = newValue} + } + + /// + /// Enable/Disable the environmental measurement plugin on-device display + var environmentalMeasurementPluginScreenEnabled: Bool { + get {return _storage._environmentalMeasurementPluginScreenEnabled} + set {_uniqueStorage()._environmentalMeasurementPluginScreenEnabled = newValue} + } + + /// + /// Sometimes sensor reads can fail. + /// If this happens, we will retry a configurable number of attempts, + /// each attempt will be delayed by the minimum required refresh rate for that sensor + var environmentalMeasurementPluginReadErrorCountThreshold: UInt32 { + get {return _storage._environmentalMeasurementPluginReadErrorCountThreshold} + set {_uniqueStorage()._environmentalMeasurementPluginReadErrorCountThreshold = newValue} + } + + /// + /// Interval in seconds of how often we should try to send our + /// measurements to the mesh + var environmentalMeasurementPluginUpdateInterval: UInt32 { + get {return _storage._environmentalMeasurementPluginUpdateInterval} + set {_uniqueStorage()._environmentalMeasurementPluginUpdateInterval = newValue} + } + + /// + /// Sometimes we can end up with more than read_error_count_threshold failures. + /// In this case, we will stop trying to read from the sensor for a while. + /// Wait this long until trying to read from the sensor again + var environmentalMeasurementPluginRecoveryInterval: UInt32 { + get {return _storage._environmentalMeasurementPluginRecoveryInterval} + set {_uniqueStorage()._environmentalMeasurementPluginRecoveryInterval = newValue} + } + + /// + /// We'll always read the sensor in Celsius, but sometimes we might want to + /// display the results in Farenheit as a "user preference". + var environmentalMeasurementPluginDisplayFarenheit: Bool { + get {return _storage._environmentalMeasurementPluginDisplayFarenheit} + set {_uniqueStorage()._environmentalMeasurementPluginDisplayFarenheit = newValue} + } + + /// + /// Specify the sensor type + var environmentalMeasurementPluginSensorType: RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType { + get {return _storage._environmentalMeasurementPluginSensorType} + set {_uniqueStorage()._environmentalMeasurementPluginSensorType = newValue} + } + + /// + /// Specify the peferred GPIO Pin for sensor readings + var environmentalMeasurementPluginSensorPin: UInt32 { + get {return _storage._environmentalMeasurementPluginSensorPin} + set {_uniqueStorage()._environmentalMeasurementPluginSensorPin = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum EnvironmentalMeasurementSensorType: SwiftProtobuf.Enum { + typealias RawValue = Int + case dht11 // = 0 + case UNRECOGNIZED(Int) + + init() { + self = .dht11 + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .dht11 + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .dht11: return 0 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance + } + + init() {} + + fileprivate var _preferences: RadioConfig.UserPreferences? = nil +} + +#if swift(>=4.2) + +extension RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType] = [ + .dht11, + ] +} + +#endif // swift(>=4.2) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension RegionCode: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "Unset"), + 1: .same(proto: "US"), + 2: .same(proto: "EU433"), + 3: .same(proto: "EU865"), + 4: .same(proto: "CN"), + 5: .same(proto: "JP"), + 6: .same(proto: "ANZ"), + 7: .same(proto: "KR"), + 8: .same(proto: "TW"), + 9: .same(proto: "RU"), + ] +} + +extension ChargeCurrent: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "MAUnset"), + 1: .same(proto: "MA100"), + 2: .same(proto: "MA190"), + 3: .same(proto: "MA280"), + 4: .same(proto: "MA360"), + 5: .same(proto: "MA450"), + 6: .same(proto: "MA550"), + 7: .same(proto: "MA630"), + 8: .same(proto: "MA700"), + 9: .same(proto: "MA780"), + 10: .same(proto: "MA880"), + 11: .same(proto: "MA960"), + 12: .same(proto: "MA1000"), + 13: .same(proto: "MA1080"), + 14: .same(proto: "MA1160"), + 15: .same(proto: "MA1240"), + 16: .same(proto: "MA1320"), + ] +} + +extension GpsOperation: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "GpsOpUnset"), + 1: .same(proto: "GpsOpStationary"), + 2: .same(proto: "GpsOpMobile"), + 3: .same(proto: "GpsOpTimeOnly"), + 4: .same(proto: "GpsOpDisabled"), + ] +} + +extension GpsCoordinateFormat: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "GpsFormatDec"), + 1: .same(proto: "GpsFormatDMS"), + 2: .same(proto: "GpsFormatUTM"), + 3: .same(proto: "GpsFormatMGRS"), + 4: .same(proto: "GpsFormatOLC"), + 5: .same(proto: "GpsFormatOSGR"), + ] +} + +extension LocationSharing: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "LocUnset"), + 1: .same(proto: "LocEnabled"), + 2: .same(proto: "LocDisabled"), + ] +} + +extension RadioConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "RadioConfig" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "preferences"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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: &self._preferences) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._preferences { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RadioConfig, rhs: RadioConfig) -> Bool { + if lhs._preferences != rhs._preferences {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RadioConfig.UserPreferences: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = RadioConfig.protoMessageName + ".UserPreferences" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "position_broadcast_secs"), + 2: .standard(proto: "send_owner_interval"), + 4: .standard(proto: "wait_bluetooth_secs"), + 5: .standard(proto: "screen_on_secs"), + 6: .standard(proto: "phone_timeout_secs"), + 7: .standard(proto: "phone_sds_timeout_sec"), + 8: .standard(proto: "mesh_sds_timeout_secs"), + 9: .standard(proto: "sds_secs"), + 10: .standard(proto: "ls_secs"), + 11: .standard(proto: "min_wake_secs"), + 12: .standard(proto: "wifi_ssid"), + 13: .standard(proto: "wifi_password"), + 14: .standard(proto: "wifi_ap_mode"), + 15: .same(proto: "region"), + 16: .standard(proto: "charge_current"), + 37: .standard(proto: "is_router"), + 38: .standard(proto: "is_low_power"), + 39: .standard(proto: "fixed_position"), + 40: .standard(proto: "serial_disabled"), + 32: .standard(proto: "location_share"), + 33: .standard(proto: "gps_operation"), + 34: .standard(proto: "gps_update_interval"), + 36: .standard(proto: "gps_attempt_time"), + 41: .standard(proto: "frequency_offset"), + 42: .standard(proto: "mqtt_server"), + 43: .standard(proto: "mqtt_disabled"), + 44: .standard(proto: "gps_format"), + 100: .standard(proto: "factory_reset"), + 101: .standard(proto: "debug_log_enabled"), + 103: .standard(proto: "ignore_incoming"), + 120: .standard(proto: "serialplugin_enabled"), + 121: .standard(proto: "serialplugin_echo"), + 122: .standard(proto: "serialplugin_rxd"), + 123: .standard(proto: "serialplugin_txd"), + 124: .standard(proto: "serialplugin_timeout"), + 125: .standard(proto: "serialplugin_mode"), + 126: .standard(proto: "ext_notification_plugin_enabled"), + 127: .standard(proto: "ext_notification_plugin_output_ms"), + 128: .standard(proto: "ext_notification_plugin_output"), + 129: .standard(proto: "ext_notification_plugin_active"), + 130: .standard(proto: "ext_notification_plugin_alert_message"), + 131: .standard(proto: "ext_notification_plugin_alert_bell"), + 132: .standard(proto: "range_test_plugin_enabled"), + 133: .standard(proto: "range_test_plugin_sender"), + 134: .standard(proto: "range_test_plugin_save"), + 148: .standard(proto: "store_forward_plugin_enabled"), + 137: .standard(proto: "store_forward_plugin_records"), + 140: .standard(proto: "environmental_measurement_plugin_measurement_enabled"), + 141: .standard(proto: "environmental_measurement_plugin_screen_enabled"), + 142: .standard(proto: "environmental_measurement_plugin_read_error_count_threshold"), + 143: .standard(proto: "environmental_measurement_plugin_update_interval"), + 144: .standard(proto: "environmental_measurement_plugin_recovery_interval"), + 145: .standard(proto: "environmental_measurement_plugin_display_farenheit"), + 146: .standard(proto: "environmental_measurement_plugin_sensor_type"), + 147: .standard(proto: "environmental_measurement_plugin_sensor_pin"), + ] + + fileprivate class _StorageClass { + var _positionBroadcastSecs: UInt32 = 0 + var _sendOwnerInterval: UInt32 = 0 + var _waitBluetoothSecs: UInt32 = 0 + var _screenOnSecs: UInt32 = 0 + var _phoneTimeoutSecs: UInt32 = 0 + var _phoneSdsTimeoutSec: UInt32 = 0 + var _meshSdsTimeoutSecs: UInt32 = 0 + var _sdsSecs: UInt32 = 0 + var _lsSecs: UInt32 = 0 + var _minWakeSecs: UInt32 = 0 + var _wifiSsid: String = String() + var _wifiPassword: String = String() + var _wifiApMode: Bool = false + var _region: RegionCode = .unset + var _chargeCurrent: ChargeCurrent = .maunset + var _isRouter: Bool = false + var _isLowPower: Bool = false + var _fixedPosition: Bool = false + var _serialDisabled: Bool = false + var _locationShare: LocationSharing = .locUnset + var _gpsOperation: GpsOperation = .gpsOpUnset + var _gpsUpdateInterval: UInt32 = 0 + var _gpsAttemptTime: UInt32 = 0 + var _frequencyOffset: Float = 0 + var _mqttServer: String = String() + var _mqttDisabled: Bool = false + var _gpsFormat: GpsCoordinateFormat = .gpsFormatDec + var _factoryReset: Bool = false + var _debugLogEnabled: Bool = false + var _ignoreIncoming: [UInt32] = [] + var _serialpluginEnabled: Bool = false + var _serialpluginEcho: Bool = false + var _serialpluginRxd: UInt32 = 0 + var _serialpluginTxd: UInt32 = 0 + var _serialpluginTimeout: UInt32 = 0 + var _serialpluginMode: UInt32 = 0 + var _extNotificationPluginEnabled: Bool = false + var _extNotificationPluginOutputMs: UInt32 = 0 + var _extNotificationPluginOutput: UInt32 = 0 + var _extNotificationPluginActive: Bool = false + var _extNotificationPluginAlertMessage: Bool = false + var _extNotificationPluginAlertBell: Bool = false + var _rangeTestPluginEnabled: Bool = false + var _rangeTestPluginSender: UInt32 = 0 + var _rangeTestPluginSave: Bool = false + var _storeForwardPluginEnabled: Bool = false + var _storeForwardPluginRecords: UInt32 = 0 + var _environmentalMeasurementPluginMeasurementEnabled: Bool = false + var _environmentalMeasurementPluginScreenEnabled: Bool = false + var _environmentalMeasurementPluginReadErrorCountThreshold: UInt32 = 0 + var _environmentalMeasurementPluginUpdateInterval: UInt32 = 0 + var _environmentalMeasurementPluginRecoveryInterval: UInt32 = 0 + var _environmentalMeasurementPluginDisplayFarenheit: Bool = false + var _environmentalMeasurementPluginSensorType: RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType = .dht11 + var _environmentalMeasurementPluginSensorPin: UInt32 = 0 + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _positionBroadcastSecs = source._positionBroadcastSecs + _sendOwnerInterval = source._sendOwnerInterval + _waitBluetoothSecs = source._waitBluetoothSecs + _screenOnSecs = source._screenOnSecs + _phoneTimeoutSecs = source._phoneTimeoutSecs + _phoneSdsTimeoutSec = source._phoneSdsTimeoutSec + _meshSdsTimeoutSecs = source._meshSdsTimeoutSecs + _sdsSecs = source._sdsSecs + _lsSecs = source._lsSecs + _minWakeSecs = source._minWakeSecs + _wifiSsid = source._wifiSsid + _wifiPassword = source._wifiPassword + _wifiApMode = source._wifiApMode + _region = source._region + _chargeCurrent = source._chargeCurrent + _isRouter = source._isRouter + _isLowPower = source._isLowPower + _fixedPosition = source._fixedPosition + _serialDisabled = source._serialDisabled + _locationShare = source._locationShare + _gpsOperation = source._gpsOperation + _gpsUpdateInterval = source._gpsUpdateInterval + _gpsAttemptTime = source._gpsAttemptTime + _frequencyOffset = source._frequencyOffset + _mqttServer = source._mqttServer + _mqttDisabled = source._mqttDisabled + _gpsFormat = source._gpsFormat + _factoryReset = source._factoryReset + _debugLogEnabled = source._debugLogEnabled + _ignoreIncoming = source._ignoreIncoming + _serialpluginEnabled = source._serialpluginEnabled + _serialpluginEcho = source._serialpluginEcho + _serialpluginRxd = source._serialpluginRxd + _serialpluginTxd = source._serialpluginTxd + _serialpluginTimeout = source._serialpluginTimeout + _serialpluginMode = source._serialpluginMode + _extNotificationPluginEnabled = source._extNotificationPluginEnabled + _extNotificationPluginOutputMs = source._extNotificationPluginOutputMs + _extNotificationPluginOutput = source._extNotificationPluginOutput + _extNotificationPluginActive = source._extNotificationPluginActive + _extNotificationPluginAlertMessage = source._extNotificationPluginAlertMessage + _extNotificationPluginAlertBell = source._extNotificationPluginAlertBell + _rangeTestPluginEnabled = source._rangeTestPluginEnabled + _rangeTestPluginSender = source._rangeTestPluginSender + _rangeTestPluginSave = source._rangeTestPluginSave + _storeForwardPluginEnabled = source._storeForwardPluginEnabled + _storeForwardPluginRecords = source._storeForwardPluginRecords + _environmentalMeasurementPluginMeasurementEnabled = source._environmentalMeasurementPluginMeasurementEnabled + _environmentalMeasurementPluginScreenEnabled = source._environmentalMeasurementPluginScreenEnabled + _environmentalMeasurementPluginReadErrorCountThreshold = source._environmentalMeasurementPluginReadErrorCountThreshold + _environmentalMeasurementPluginUpdateInterval = source._environmentalMeasurementPluginUpdateInterval + _environmentalMeasurementPluginRecoveryInterval = source._environmentalMeasurementPluginRecoveryInterval + _environmentalMeasurementPluginDisplayFarenheit = source._environmentalMeasurementPluginDisplayFarenheit + _environmentalMeasurementPluginSensorType = source._environmentalMeasurementPluginSensorType + _environmentalMeasurementPluginSensorPin = source._environmentalMeasurementPluginSensorPin + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(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.decodeSingularUInt32Field(value: &_storage._positionBroadcastSecs) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &_storage._sendOwnerInterval) }() + case 4: try { try decoder.decodeSingularUInt32Field(value: &_storage._waitBluetoothSecs) }() + case 5: try { try decoder.decodeSingularUInt32Field(value: &_storage._screenOnSecs) }() + case 6: try { try decoder.decodeSingularUInt32Field(value: &_storage._phoneTimeoutSecs) }() + case 7: try { try decoder.decodeSingularUInt32Field(value: &_storage._phoneSdsTimeoutSec) }() + case 8: try { try decoder.decodeSingularUInt32Field(value: &_storage._meshSdsTimeoutSecs) }() + case 9: try { try decoder.decodeSingularUInt32Field(value: &_storage._sdsSecs) }() + case 10: try { try decoder.decodeSingularUInt32Field(value: &_storage._lsSecs) }() + case 11: try { try decoder.decodeSingularUInt32Field(value: &_storage._minWakeSecs) }() + case 12: try { try decoder.decodeSingularStringField(value: &_storage._wifiSsid) }() + case 13: try { try decoder.decodeSingularStringField(value: &_storage._wifiPassword) }() + case 14: try { try decoder.decodeSingularBoolField(value: &_storage._wifiApMode) }() + case 15: try { try decoder.decodeSingularEnumField(value: &_storage._region) }() + case 16: try { try decoder.decodeSingularEnumField(value: &_storage._chargeCurrent) }() + case 32: try { try decoder.decodeSingularEnumField(value: &_storage._locationShare) }() + case 33: try { try decoder.decodeSingularEnumField(value: &_storage._gpsOperation) }() + case 34: try { try decoder.decodeSingularUInt32Field(value: &_storage._gpsUpdateInterval) }() + case 36: try { try decoder.decodeSingularUInt32Field(value: &_storage._gpsAttemptTime) }() + case 37: try { try decoder.decodeSingularBoolField(value: &_storage._isRouter) }() + case 38: try { try decoder.decodeSingularBoolField(value: &_storage._isLowPower) }() + case 39: try { try decoder.decodeSingularBoolField(value: &_storage._fixedPosition) }() + case 40: try { try decoder.decodeSingularBoolField(value: &_storage._serialDisabled) }() + case 41: try { try decoder.decodeSingularFloatField(value: &_storage._frequencyOffset) }() + case 42: try { try decoder.decodeSingularStringField(value: &_storage._mqttServer) }() + case 43: try { try decoder.decodeSingularBoolField(value: &_storage._mqttDisabled) }() + case 44: try { try decoder.decodeSingularEnumField(value: &_storage._gpsFormat) }() + case 100: try { try decoder.decodeSingularBoolField(value: &_storage._factoryReset) }() + case 101: try { try decoder.decodeSingularBoolField(value: &_storage._debugLogEnabled) }() + case 103: try { try decoder.decodeRepeatedUInt32Field(value: &_storage._ignoreIncoming) }() + case 120: try { try decoder.decodeSingularBoolField(value: &_storage._serialpluginEnabled) }() + case 121: try { try decoder.decodeSingularBoolField(value: &_storage._serialpluginEcho) }() + case 122: try { try decoder.decodeSingularUInt32Field(value: &_storage._serialpluginRxd) }() + case 123: try { try decoder.decodeSingularUInt32Field(value: &_storage._serialpluginTxd) }() + case 124: try { try decoder.decodeSingularUInt32Field(value: &_storage._serialpluginTimeout) }() + case 125: try { try decoder.decodeSingularUInt32Field(value: &_storage._serialpluginMode) }() + case 126: try { try decoder.decodeSingularBoolField(value: &_storage._extNotificationPluginEnabled) }() + case 127: try { try decoder.decodeSingularUInt32Field(value: &_storage._extNotificationPluginOutputMs) }() + case 128: try { try decoder.decodeSingularUInt32Field(value: &_storage._extNotificationPluginOutput) }() + case 129: try { try decoder.decodeSingularBoolField(value: &_storage._extNotificationPluginActive) }() + case 130: try { try decoder.decodeSingularBoolField(value: &_storage._extNotificationPluginAlertMessage) }() + case 131: try { try decoder.decodeSingularBoolField(value: &_storage._extNotificationPluginAlertBell) }() + case 132: try { try decoder.decodeSingularBoolField(value: &_storage._rangeTestPluginEnabled) }() + case 133: try { try decoder.decodeSingularUInt32Field(value: &_storage._rangeTestPluginSender) }() + case 134: try { try decoder.decodeSingularBoolField(value: &_storage._rangeTestPluginSave) }() + case 137: try { try decoder.decodeSingularUInt32Field(value: &_storage._storeForwardPluginRecords) }() + case 140: try { try decoder.decodeSingularBoolField(value: &_storage._environmentalMeasurementPluginMeasurementEnabled) }() + case 141: try { try decoder.decodeSingularBoolField(value: &_storage._environmentalMeasurementPluginScreenEnabled) }() + case 142: try { try decoder.decodeSingularUInt32Field(value: &_storage._environmentalMeasurementPluginReadErrorCountThreshold) }() + case 143: try { try decoder.decodeSingularUInt32Field(value: &_storage._environmentalMeasurementPluginUpdateInterval) }() + case 144: try { try decoder.decodeSingularUInt32Field(value: &_storage._environmentalMeasurementPluginRecoveryInterval) }() + case 145: try { try decoder.decodeSingularBoolField(value: &_storage._environmentalMeasurementPluginDisplayFarenheit) }() + case 146: try { try decoder.decodeSingularEnumField(value: &_storage._environmentalMeasurementPluginSensorType) }() + case 147: try { try decoder.decodeSingularUInt32Field(value: &_storage._environmentalMeasurementPluginSensorPin) }() + case 148: try { try decoder.decodeSingularBoolField(value: &_storage._storeForwardPluginEnabled) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if _storage._positionBroadcastSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._positionBroadcastSecs, fieldNumber: 1) + } + if _storage._sendOwnerInterval != 0 { + try visitor.visitSingularUInt32Field(value: _storage._sendOwnerInterval, fieldNumber: 2) + } + if _storage._waitBluetoothSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._waitBluetoothSecs, fieldNumber: 4) + } + if _storage._screenOnSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._screenOnSecs, fieldNumber: 5) + } + if _storage._phoneTimeoutSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._phoneTimeoutSecs, fieldNumber: 6) + } + if _storage._phoneSdsTimeoutSec != 0 { + try visitor.visitSingularUInt32Field(value: _storage._phoneSdsTimeoutSec, fieldNumber: 7) + } + if _storage._meshSdsTimeoutSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._meshSdsTimeoutSecs, fieldNumber: 8) + } + if _storage._sdsSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._sdsSecs, fieldNumber: 9) + } + if _storage._lsSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._lsSecs, fieldNumber: 10) + } + if _storage._minWakeSecs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._minWakeSecs, fieldNumber: 11) + } + if !_storage._wifiSsid.isEmpty { + try visitor.visitSingularStringField(value: _storage._wifiSsid, fieldNumber: 12) + } + if !_storage._wifiPassword.isEmpty { + try visitor.visitSingularStringField(value: _storage._wifiPassword, fieldNumber: 13) + } + if _storage._wifiApMode != false { + try visitor.visitSingularBoolField(value: _storage._wifiApMode, fieldNumber: 14) + } + if _storage._region != .unset { + try visitor.visitSingularEnumField(value: _storage._region, fieldNumber: 15) + } + if _storage._chargeCurrent != .maunset { + try visitor.visitSingularEnumField(value: _storage._chargeCurrent, fieldNumber: 16) + } + if _storage._locationShare != .locUnset { + try visitor.visitSingularEnumField(value: _storage._locationShare, fieldNumber: 32) + } + if _storage._gpsOperation != .gpsOpUnset { + try visitor.visitSingularEnumField(value: _storage._gpsOperation, fieldNumber: 33) + } + if _storage._gpsUpdateInterval != 0 { + try visitor.visitSingularUInt32Field(value: _storage._gpsUpdateInterval, fieldNumber: 34) + } + if _storage._gpsAttemptTime != 0 { + try visitor.visitSingularUInt32Field(value: _storage._gpsAttemptTime, fieldNumber: 36) + } + if _storage._isRouter != false { + try visitor.visitSingularBoolField(value: _storage._isRouter, fieldNumber: 37) + } + if _storage._isLowPower != false { + try visitor.visitSingularBoolField(value: _storage._isLowPower, fieldNumber: 38) + } + if _storage._fixedPosition != false { + try visitor.visitSingularBoolField(value: _storage._fixedPosition, fieldNumber: 39) + } + if _storage._serialDisabled != false { + try visitor.visitSingularBoolField(value: _storage._serialDisabled, fieldNumber: 40) + } + if _storage._frequencyOffset != 0 { + try visitor.visitSingularFloatField(value: _storage._frequencyOffset, fieldNumber: 41) + } + if !_storage._mqttServer.isEmpty { + try visitor.visitSingularStringField(value: _storage._mqttServer, fieldNumber: 42) + } + if _storage._mqttDisabled != false { + try visitor.visitSingularBoolField(value: _storage._mqttDisabled, fieldNumber: 43) + } + if _storage._gpsFormat != .gpsFormatDec { + try visitor.visitSingularEnumField(value: _storage._gpsFormat, fieldNumber: 44) + } + if _storage._factoryReset != false { + try visitor.visitSingularBoolField(value: _storage._factoryReset, fieldNumber: 100) + } + if _storage._debugLogEnabled != false { + try visitor.visitSingularBoolField(value: _storage._debugLogEnabled, fieldNumber: 101) + } + if !_storage._ignoreIncoming.isEmpty { + try visitor.visitPackedUInt32Field(value: _storage._ignoreIncoming, fieldNumber: 103) + } + if _storage._serialpluginEnabled != false { + try visitor.visitSingularBoolField(value: _storage._serialpluginEnabled, fieldNumber: 120) + } + if _storage._serialpluginEcho != false { + try visitor.visitSingularBoolField(value: _storage._serialpluginEcho, fieldNumber: 121) + } + if _storage._serialpluginRxd != 0 { + try visitor.visitSingularUInt32Field(value: _storage._serialpluginRxd, fieldNumber: 122) + } + if _storage._serialpluginTxd != 0 { + try visitor.visitSingularUInt32Field(value: _storage._serialpluginTxd, fieldNumber: 123) + } + if _storage._serialpluginTimeout != 0 { + try visitor.visitSingularUInt32Field(value: _storage._serialpluginTimeout, fieldNumber: 124) + } + if _storage._serialpluginMode != 0 { + try visitor.visitSingularUInt32Field(value: _storage._serialpluginMode, fieldNumber: 125) + } + if _storage._extNotificationPluginEnabled != false { + try visitor.visitSingularBoolField(value: _storage._extNotificationPluginEnabled, fieldNumber: 126) + } + if _storage._extNotificationPluginOutputMs != 0 { + try visitor.visitSingularUInt32Field(value: _storage._extNotificationPluginOutputMs, fieldNumber: 127) + } + if _storage._extNotificationPluginOutput != 0 { + try visitor.visitSingularUInt32Field(value: _storage._extNotificationPluginOutput, fieldNumber: 128) + } + if _storage._extNotificationPluginActive != false { + try visitor.visitSingularBoolField(value: _storage._extNotificationPluginActive, fieldNumber: 129) + } + if _storage._extNotificationPluginAlertMessage != false { + try visitor.visitSingularBoolField(value: _storage._extNotificationPluginAlertMessage, fieldNumber: 130) + } + if _storage._extNotificationPluginAlertBell != false { + try visitor.visitSingularBoolField(value: _storage._extNotificationPluginAlertBell, fieldNumber: 131) + } + if _storage._rangeTestPluginEnabled != false { + try visitor.visitSingularBoolField(value: _storage._rangeTestPluginEnabled, fieldNumber: 132) + } + if _storage._rangeTestPluginSender != 0 { + try visitor.visitSingularUInt32Field(value: _storage._rangeTestPluginSender, fieldNumber: 133) + } + if _storage._rangeTestPluginSave != false { + try visitor.visitSingularBoolField(value: _storage._rangeTestPluginSave, fieldNumber: 134) + } + if _storage._storeForwardPluginRecords != 0 { + try visitor.visitSingularUInt32Field(value: _storage._storeForwardPluginRecords, fieldNumber: 137) + } + if _storage._environmentalMeasurementPluginMeasurementEnabled != false { + try visitor.visitSingularBoolField(value: _storage._environmentalMeasurementPluginMeasurementEnabled, fieldNumber: 140) + } + if _storage._environmentalMeasurementPluginScreenEnabled != false { + try visitor.visitSingularBoolField(value: _storage._environmentalMeasurementPluginScreenEnabled, fieldNumber: 141) + } + if _storage._environmentalMeasurementPluginReadErrorCountThreshold != 0 { + try visitor.visitSingularUInt32Field(value: _storage._environmentalMeasurementPluginReadErrorCountThreshold, fieldNumber: 142) + } + if _storage._environmentalMeasurementPluginUpdateInterval != 0 { + try visitor.visitSingularUInt32Field(value: _storage._environmentalMeasurementPluginUpdateInterval, fieldNumber: 143) + } + if _storage._environmentalMeasurementPluginRecoveryInterval != 0 { + try visitor.visitSingularUInt32Field(value: _storage._environmentalMeasurementPluginRecoveryInterval, fieldNumber: 144) + } + if _storage._environmentalMeasurementPluginDisplayFarenheit != false { + try visitor.visitSingularBoolField(value: _storage._environmentalMeasurementPluginDisplayFarenheit, fieldNumber: 145) + } + if _storage._environmentalMeasurementPluginSensorType != .dht11 { + try visitor.visitSingularEnumField(value: _storage._environmentalMeasurementPluginSensorType, fieldNumber: 146) + } + if _storage._environmentalMeasurementPluginSensorPin != 0 { + try visitor.visitSingularUInt32Field(value: _storage._environmentalMeasurementPluginSensorPin, fieldNumber: 147) + } + if _storage._storeForwardPluginEnabled != false { + try visitor.visitSingularBoolField(value: _storage._storeForwardPluginEnabled, fieldNumber: 148) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RadioConfig.UserPreferences, rhs: RadioConfig.UserPreferences) -> 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._positionBroadcastSecs != rhs_storage._positionBroadcastSecs {return false} + if _storage._sendOwnerInterval != rhs_storage._sendOwnerInterval {return false} + if _storage._waitBluetoothSecs != rhs_storage._waitBluetoothSecs {return false} + if _storage._screenOnSecs != rhs_storage._screenOnSecs {return false} + if _storage._phoneTimeoutSecs != rhs_storage._phoneTimeoutSecs {return false} + if _storage._phoneSdsTimeoutSec != rhs_storage._phoneSdsTimeoutSec {return false} + if _storage._meshSdsTimeoutSecs != rhs_storage._meshSdsTimeoutSecs {return false} + if _storage._sdsSecs != rhs_storage._sdsSecs {return false} + if _storage._lsSecs != rhs_storage._lsSecs {return false} + if _storage._minWakeSecs != rhs_storage._minWakeSecs {return false} + if _storage._wifiSsid != rhs_storage._wifiSsid {return false} + if _storage._wifiPassword != rhs_storage._wifiPassword {return false} + if _storage._wifiApMode != rhs_storage._wifiApMode {return false} + if _storage._region != rhs_storage._region {return false} + if _storage._chargeCurrent != rhs_storage._chargeCurrent {return false} + if _storage._isRouter != rhs_storage._isRouter {return false} + if _storage._isLowPower != rhs_storage._isLowPower {return false} + if _storage._fixedPosition != rhs_storage._fixedPosition {return false} + if _storage._serialDisabled != rhs_storage._serialDisabled {return false} + if _storage._locationShare != rhs_storage._locationShare {return false} + if _storage._gpsOperation != rhs_storage._gpsOperation {return false} + if _storage._gpsUpdateInterval != rhs_storage._gpsUpdateInterval {return false} + if _storage._gpsAttemptTime != rhs_storage._gpsAttemptTime {return false} + if _storage._frequencyOffset != rhs_storage._frequencyOffset {return false} + if _storage._mqttServer != rhs_storage._mqttServer {return false} + if _storage._mqttDisabled != rhs_storage._mqttDisabled {return false} + if _storage._gpsFormat != rhs_storage._gpsFormat {return false} + if _storage._factoryReset != rhs_storage._factoryReset {return false} + if _storage._debugLogEnabled != rhs_storage._debugLogEnabled {return false} + if _storage._ignoreIncoming != rhs_storage._ignoreIncoming {return false} + if _storage._serialpluginEnabled != rhs_storage._serialpluginEnabled {return false} + if _storage._serialpluginEcho != rhs_storage._serialpluginEcho {return false} + if _storage._serialpluginRxd != rhs_storage._serialpluginRxd {return false} + if _storage._serialpluginTxd != rhs_storage._serialpluginTxd {return false} + if _storage._serialpluginTimeout != rhs_storage._serialpluginTimeout {return false} + if _storage._serialpluginMode != rhs_storage._serialpluginMode {return false} + if _storage._extNotificationPluginEnabled != rhs_storage._extNotificationPluginEnabled {return false} + if _storage._extNotificationPluginOutputMs != rhs_storage._extNotificationPluginOutputMs {return false} + if _storage._extNotificationPluginOutput != rhs_storage._extNotificationPluginOutput {return false} + if _storage._extNotificationPluginActive != rhs_storage._extNotificationPluginActive {return false} + if _storage._extNotificationPluginAlertMessage != rhs_storage._extNotificationPluginAlertMessage {return false} + if _storage._extNotificationPluginAlertBell != rhs_storage._extNotificationPluginAlertBell {return false} + if _storage._rangeTestPluginEnabled != rhs_storage._rangeTestPluginEnabled {return false} + if _storage._rangeTestPluginSender != rhs_storage._rangeTestPluginSender {return false} + if _storage._rangeTestPluginSave != rhs_storage._rangeTestPluginSave {return false} + if _storage._storeForwardPluginEnabled != rhs_storage._storeForwardPluginEnabled {return false} + if _storage._storeForwardPluginRecords != rhs_storage._storeForwardPluginRecords {return false} + if _storage._environmentalMeasurementPluginMeasurementEnabled != rhs_storage._environmentalMeasurementPluginMeasurementEnabled {return false} + if _storage._environmentalMeasurementPluginScreenEnabled != rhs_storage._environmentalMeasurementPluginScreenEnabled {return false} + if _storage._environmentalMeasurementPluginReadErrorCountThreshold != rhs_storage._environmentalMeasurementPluginReadErrorCountThreshold {return false} + if _storage._environmentalMeasurementPluginUpdateInterval != rhs_storage._environmentalMeasurementPluginUpdateInterval {return false} + if _storage._environmentalMeasurementPluginRecoveryInterval != rhs_storage._environmentalMeasurementPluginRecoveryInterval {return false} + if _storage._environmentalMeasurementPluginDisplayFarenheit != rhs_storage._environmentalMeasurementPluginDisplayFarenheit {return false} + if _storage._environmentalMeasurementPluginSensorType != rhs_storage._environmentalMeasurementPluginSensorType {return false} + if _storage._environmentalMeasurementPluginSensorPin != rhs_storage._environmentalMeasurementPluginSensorPin {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "DHT11"), + ] +} diff --git a/MeshtasticClient/Protobufs/remote_hardware.pb.swift b/MeshtasticClient/Protobufs/remote_hardware.pb.swift new file mode 100644 index 00000000..f2a300da --- /dev/null +++ b/MeshtasticClient/Protobufs/remote_hardware.pb.swift @@ -0,0 +1,190 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: remote_hardware.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// +/// An example app to show off the plugin system. This message is used for +/// REMOTE_HARDWARE_APP PortNums. +/// +/// Also provides easy remote access to any GPIO. +/// +/// In the future other remote hardware operations can be added based on user interest +/// (i.e. serial output, spi/i2c input/output). +/// +/// FIXME - currently this feature is turned on by default which is dangerous +/// because no security yet (beyond the channel mechanism). +/// It should be off by default and then protected based on some TBD mechanism +/// (a special channel once multichannel support is included?) +struct HardwareMessage { + // 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. + + /// + /// What type of HardwareMessage is this? + var typ: HardwareMessage.TypeEnum = .unset + + /// + /// What gpios are we changing. Not used for all MessageTypes, see MessageType for details + var gpioMask: UInt64 = 0 + + /// + /// For gpios that were listed in gpio_mask as valid, what are the signal levels for those gpios. + /// Not used for all MessageTypes, see MessageType for details + var gpioValue: UInt64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum TypeEnum: SwiftProtobuf.Enum { + typealias RawValue = Int + + /// + /// Unset/unused + case unset // = 0 + + /// + /// Set gpio gpios based on gpio_mask/gpio_value + case writeGpios // = 1 + + /// + /// We are now interested in watching the gpio_mask gpios. + /// If the selected gpios change, please broadcast GPIOS_CHANGED. + /// Will implicitly change the gpios requested to be INPUT gpios. + case watchGpios // = 2 + + /// + /// The gpios listed in gpio_mask have changed, the new values are listed in gpio_value + case gpiosChanged // = 3 + + /// + /// Read the gpios specified in gpio_mask, send back a READ_GPIOS_REPLY reply with gpio_value populated + case readGpios // = 4 + + /// + /// A reply to READ_GPIOS. gpio_mask and gpio_value will be populated + case readGpiosReply // = 5 + case UNRECOGNIZED(Int) + + init() { + self = .unset + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 1: self = .writeGpios + case 2: self = .watchGpios + case 3: self = .gpiosChanged + case 4: self = .readGpios + case 5: self = .readGpiosReply + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .unset: return 0 + case .writeGpios: return 1 + case .watchGpios: return 2 + case .gpiosChanged: return 3 + case .readGpios: return 4 + case .readGpiosReply: return 5 + case .UNRECOGNIZED(let i): return i + } + } + + } + + init() {} +} + +#if swift(>=4.2) + +extension HardwareMessage.TypeEnum: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [HardwareMessage.TypeEnum] = [ + .unset, + .writeGpios, + .watchGpios, + .gpiosChanged, + .readGpios, + .readGpiosReply, + ] +} + +#endif // swift(>=4.2) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension HardwareMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "HardwareMessage" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "typ"), + 2: .standard(proto: "gpio_mask"), + 3: .standard(proto: "gpio_value"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + 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.decodeSingularEnumField(value: &self.typ) }() + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.gpioMask) }() + case 3: try { try decoder.decodeSingularUInt64Field(value: &self.gpioValue) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.typ != .unset { + try visitor.visitSingularEnumField(value: self.typ, fieldNumber: 1) + } + if self.gpioMask != 0 { + try visitor.visitSingularUInt64Field(value: self.gpioMask, fieldNumber: 2) + } + if self.gpioValue != 0 { + try visitor.visitSingularUInt64Field(value: self.gpioValue, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: HardwareMessage, rhs: HardwareMessage) -> Bool { + if lhs.typ != rhs.typ {return false} + if lhs.gpioMask != rhs.gpioMask {return false} + if lhs.gpioValue != rhs.gpioValue {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension HardwareMessage.TypeEnum: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSET"), + 1: .same(proto: "WRITE_GPIOS"), + 2: .same(proto: "WATCH_GPIOS"), + 3: .same(proto: "GPIOS_CHANGED"), + 4: .same(proto: "READ_GPIOS"), + 5: .same(proto: "READ_GPIOS_REPLY"), + ] +} diff --git a/MeshtasticClient/Resources/nodeInfo.json b/MeshtasticClient/Resources/nodeInfo.json new file mode 100644 index 00000000..3c121b62 --- /dev/null +++ b/MeshtasticClient/Resources/nodeInfo.json @@ -0,0 +1,38 @@ +[{ + "nodeInfo": { + "num":3186677820, + "user":{ + "id":"!bdf0d83c", + "longName":"Garth Vander Houwen", + "shortName":"GVH", + "macaddr":"fJ698Ng8", + "hwModel":"TBEAM" + }, + "position":{ + "latitudeI":476040257, + "longitudeI":-1221545412, + "altitude":11, + "batteryLevel":100, + "time":1631384279 + }, + "lastHeard":1631384279 + }, + { + "nodeInfo":{ + "num":2792101487, + "user":{ + "id":"!a66c166f", + "longName":"RAK Solar 2", + "shortName":"RS2", + "macaddr":"8eambBZv", + "hwModel":"RAK4631" + }, + "position":{ + "batteryLevel":88, + "time":1631297585 + }, + "lastHeard":1631383493, + "snr":12.0 + } + } +}] diff --git a/MeshtasticClient/Views/Devices/Bluetooth.swift b/MeshtasticClient/Views/Devices/Bluetooth.swift deleted file mode 100644 index 34ae3821..00000000 --- a/MeshtasticClient/Views/Devices/Bluetooth.swift +++ /dev/null @@ -1,4 +0,0 @@ -import SwiftUI -import CoreBluetooth - - diff --git a/MeshtasticClient/Views/Devices/DeviceBLE.swift b/MeshtasticClient/Views/Devices/DeviceBLE.swift index d3baaaf7..6206ef8b 100644 --- a/MeshtasticClient/Views/Devices/DeviceBLE.swift +++ b/MeshtasticClient/Views/Devices/DeviceBLE.swift @@ -5,6 +5,9 @@ // Created by Garth Vander Houwen on 8/18/21. // +// Abstract: +// A view allowing you to interact with nearby meshtastic nodes + import SwiftUI import MapKit import CoreLocation @@ -19,65 +22,68 @@ struct DeviceBLE: View { modelData.devices } - var body: some View { NavigationView { - VStack { List { - Section(header: Text("Connected Device")) { + Section(header: Text("Connected Device").font(.title)) { if(bleManager.connectedPeripheral != nil){ HStack{ - Image(systemName: "dot.radiowaves.left.and.right").imageScale(.medium).foregroundColor(.green) - Text(bleManager.connectedPeripheral.name!) - Spacer() - // print(bleManager.meshtasticPeripheral) + Image(systemName: "dot.radiowaves.left.and.right").imageScale(.large).foregroundColor(.green) + Text(bleManager.connectedPeripheral.name!).font(.title2) } } + else { + Text("No device connected").font(.title2) + } }.textCase(nil) - Section(header: Text("Other Meshtastic Devices")) { + Section(header: Text("Other Meshtastic Devices").font(.title)) { ForEach(bleManager.peripherals.sorted(by: { $0.rssi > $1.rssi })) { peripheral in HStack { - - Image(systemName: "circle.fill").imageScale(.medium).foregroundColor(.gray) - + Image(systemName: "circle.fill").imageScale(.large).foregroundColor(.gray) Button(action: { self.bleManager.stopScanning() self.bleManager.disconnectDevice() self.bleManager.connectToDevice(id: peripheral.id) }) { - Text(peripheral.name) + Text(peripheral.name).font(.title2) } Spacer() - Text(String(peripheral.rssi) + " dB") + Text(String(peripheral.rssi) + " dB").font(.title3) } } }.textCase(nil) } - // Image(systemName: "dot.radiowaves.left.and.right").imageScale(.medium).foregroundColor(.green)//.rotationEffect(Angle(degrees: 90)) - Spacer() - HStack { - VStack (spacing: 10) { - Button(action: { - self.bleManager.startScanning() - }) { - Text("Start Scanning") - } - Button(action: { - self.bleManager.stopScanning() - }) { - Text("Stop Scanning") - } - }.padding() - - Spacer() - - } + HStack (spacing: 15) { + Button(action: { + self.bleManager.startScanning() + }) { + Image(systemName: "play.fill").imageScale(.large).foregroundColor(.gray) + Text("Start Scanning").font(.caption) + .font(.caption) + .foregroundColor(.gray) + } + .padding() + .background(Color(.systemGray6)) + .clipShape(Capsule()) + Spacer(minLength: 10) + Button(action: { + self.bleManager.stopScanning() + }) { + Image(systemName: "stop.fill").imageScale(.large).foregroundColor(.gray) + Text("Stop Scanning") + .font(.caption) + .foregroundColor(.gray) + } + .padding() + .background(Color(.systemGray6)) + .clipShape(Capsule()) + }.padding() Spacer() } - .navigationTitle("Nearby Devices") + .navigationTitle("Nearby BLE Devices") .navigationBarItems(leading: HStack { Button(action: { @@ -99,7 +105,5 @@ struct DeviceBLE: View { } ) }.navigationViewStyle(StackNavigationViewStyle()) - } - } diff --git a/MeshtasticClient/Views/Devices/DeviceHome.swift b/MeshtasticClient/Views/Devices/DeviceHome.swift index acf31292..387d8a33 100644 --- a/MeshtasticClient/Views/Devices/DeviceHome.swift +++ b/MeshtasticClient/Views/Devices/DeviceHome.swift @@ -1,5 +1,6 @@ // // DeviceHome.swift +// MeshtasticClient // // Created by Garth Vander Houwen on 8/7/21. // diff --git a/MeshtasticClient/Views/Devices/DeviceMap.swift b/MeshtasticClient/Views/Devices/DeviceMap.swift index 26b4d36e..eeda2dfd 100644 --- a/MeshtasticClient/Views/Devices/DeviceMap.swift +++ b/MeshtasticClient/Views/Devices/DeviceMap.swift @@ -1,6 +1,6 @@ // // DeviceMap.swift -// Landmarks +// MeshtasticClient // // Created by Garth Vander Houwen on 8/7/21. // Copyright © 2021 Apple. All rights reserved. diff --git a/MeshtasticClient/Views/Devices/DeviceRow.swift b/MeshtasticClient/Views/Devices/DeviceRow.swift index d306e62f..0cf1aa93 100644 --- a/MeshtasticClient/Views/Devices/DeviceRow.swift +++ b/MeshtasticClient/Views/Devices/DeviceRow.swift @@ -1,9 +1,11 @@ -/* -See LICENSE folder for this sample’s licensing information. - -Abstract: -A single row to be displayed in a list of landmarks. -*/ +// +// DeviceMap.swift +// MeshtasticClient +// +// Created by Garth Vander Houwen on 8/7/21. +// +// Abstract: +// A single row to be displayed in a list of landmarks. import SwiftUI