Update Protobufs, finish LoRaConfig UI

This commit is contained in:
Garth Vander Houwen 2022-06-20 12:51:55 -07:00
parent f4a7cc8bfd
commit 18630efa58
6 changed files with 202 additions and 188 deletions

View file

@ -433,8 +433,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
} else if decodedInfo.config.isInitialized {
//localConfig(config: decodedInfo.config, meshlogging: meshLoggingEnabled, context: context!, nodeLongName: self.connectedPeripheral.longName)
if meshLoggingEnabled { MeshLogger.log(" MESH PACKET received for Unknown App decodedInfo.config.isInitialized \(try! decodedInfo.packet.jsonString())") }
localConfig(config: decodedInfo.config, meshlogging: meshLoggingEnabled, context: context!, nodeLongName: self.connectedPeripheral.longName)
if meshLoggingEnabled { MeshLogger.log(" MESH PACKET received for Unknown App decodedInfo.config.isInitialized \(try! decodedInfo.config.jsonString())") }
} else {

View file

@ -9,11 +9,11 @@ import Foundation
import CoreData
import SwiftUI
func localConfig (config: LocalConfig, meshlogging: Bool, context:NSManagedObjectContext, nodeLongName: String) {
func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectContext, nodeLongName: String) {
// We don't care about any of the Power settings
// We don't want to manage wifi from the phone app and disconnect our device
if meshlogging { MeshLogger.log("⚙️ Local Config version \(config.version) received for \(nodeLongName)") }
//if meshlogging { MeshLogger.log(" Local Config version \(config.version) received for \(nodeLongName)") }
if (try! config.device.jsonString()) == "{}" {
@ -24,6 +24,26 @@ func localConfig (config: LocalConfig, meshlogging: Bool, context:NSManagedObjec
print("📟 Has Device config")
}
if (try! config.position.jsonString()) == "{}" {
print("📍 Default Position config")
} else {
print("📍 Has Position config")
}
if (try! config.power.jsonString() == "{\"lsSecs\":300}") {
print("📍 Default Power config")
print(try! config.power.jsonString())
} else {
print("📍 Has Power config")
print(try! config.power.jsonString())
}
if (try! config.display.jsonString()) == "{}" {
print("🖥️ Default Display config")
@ -33,6 +53,10 @@ func localConfig (config: LocalConfig, meshlogging: Bool, context:NSManagedObjec
print("🖥️ Has Display config")
}
if (try! config.lora.jsonString()) == "{}" {
print("📡 Default LoRa config")
@ -41,15 +65,6 @@ func localConfig (config: LocalConfig, meshlogging: Bool, context:NSManagedObjec
print("📡 Has LoRa config")
}
if (try! config.position.jsonString()) == "{}" {
print("📍 Default Position config")
} else {
print("📍 Has Position config")
}
}
func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObjectContext) -> MyInfoEntity? {

View file

@ -26,11 +26,9 @@ struct Config {
// methods supported on all messages.
///
/// TODO: REPLACE
/// Payload Variant
var payloadVariant: Config.OneOf_PayloadVariant? = nil
///
/// TODO: REPLACE
var device: Config.DeviceConfig {
get {
if case .device(let v)? = payloadVariant {return v}
@ -39,8 +37,6 @@ struct Config {
set {payloadVariant = .device(newValue)}
}
///
/// TODO: REPLACE
var position: Config.PositionConfig {
get {
if case .position(let v)? = payloadVariant {return v}
@ -49,8 +45,6 @@ struct Config {
set {payloadVariant = .position(newValue)}
}
///
/// TODO: REPLACE
var power: Config.PowerConfig {
get {
if case .power(let v)? = payloadVariant {return v}
@ -59,8 +53,6 @@ struct Config {
set {payloadVariant = .power(newValue)}
}
///
/// TODO: REPLACE
var wifi: Config.WiFiConfig {
get {
if case .wifi(let v)? = payloadVariant {return v}
@ -69,8 +61,6 @@ struct Config {
set {payloadVariant = .wifi(newValue)}
}
///
/// TODO: REPLACE
var display: Config.DisplayConfig {
get {
if case .display(let v)? = payloadVariant {return v}
@ -79,8 +69,6 @@ struct Config {
set {payloadVariant = .display(newValue)}
}
///
/// TODO: REPLACE
var lora: Config.LoRaConfig {
get {
if case .lora(let v)? = payloadVariant {return v}
@ -92,25 +80,13 @@ struct Config {
var unknownFields = SwiftProtobuf.UnknownStorage()
///
/// TODO: REPLACE
/// Payload Variant
enum OneOf_PayloadVariant: Equatable {
///
/// TODO: REPLACE
case device(Config.DeviceConfig)
///
/// TODO: REPLACE
case position(Config.PositionConfig)
///
/// TODO: REPLACE
case power(Config.PowerConfig)
///
/// TODO: REPLACE
case wifi(Config.WiFiConfig)
///
/// TODO: REPLACE
case display(Config.DisplayConfig)
///
/// TODO: REPLACE
case lora(Config.LoRaConfig)
#if !swift(>=4.1)
@ -166,7 +142,6 @@ struct Config {
///
/// 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 = false
///
@ -182,7 +157,6 @@ struct Config {
///
/// Defines the device's role on the Mesh network
/// unset - 0
enum Role: SwiftProtobuf.Enum {
typealias RawValue = Int
@ -191,24 +165,19 @@ struct Config {
case client // = 0
///
/// ClientMute device role
/// This is like the client but packets will not hop over this node. Would be
/// useful if you want to save power by not contributing to the mesh.
/// Client Mute device role
/// Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh.
case clientMute // = 1
///
/// Router device role.
/// Uses an agressive algirithem for the flood networking so packets will
/// prefer to be routed over this node. Also assume that this will be
/// unattended and so will turn off the wifi/ble radio as well as the oled screen.
/// Mesh packets will prefer to be routed over this node. This node will not be used by client apps.
/// The wifi/ble radios and the oled screen will be put to sleep.
case router // = 2
///
/// RouterClient device role
/// Uses an agressive algirithem for the flood networking so packets will
/// prefer to be routed over this node. Similiar power management as a regular
/// client, so the RouterClient can be used as both a Router and a Client. Useful
/// as a well placed base station that you could also use to send messages.
/// Router Client device role
/// Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client.
case routerClient // = 3
case UNRECOGNIZED(Int)
@ -331,6 +300,18 @@ struct Config {
///
/// Include positional timestamp (from GPS solution)
case posTimestamp // = 128
///
/// Include positional heading
/// Intended for use with vehicle not walking speeds
/// walking speeds are likely to be error prone like the compass
case posHeading // = 256
///
/// Include positional speed
/// Intended for use with vehicle not walking speeds
/// walking speeds are likely to be error prone like the compass
case posSpeed // = 512
case UNRECOGNIZED(Int)
init() {
@ -348,6 +329,8 @@ struct Config {
case 32: self = .posSatinview
case 64: self = .posSeqNos
case 128: self = .posTimestamp
case 256: self = .posHeading
case 512: self = .posSpeed
default: self = .UNRECOGNIZED(rawValue)
}
}
@ -363,6 +346,8 @@ struct Config {
case .posSatinview: return 32
case .posSeqNos: return 64
case .posTimestamp: return 128
case .posHeading: return 256
case .posSpeed: return 512
case .UNRECOGNIZED(let i): return i
}
}
@ -389,7 +374,7 @@ struct Config {
/// 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).
/// CLI Only Option
/// Advanced Option
var isPowerSaving: Bool = false
///
@ -399,11 +384,13 @@ struct Config {
///
/// Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
/// Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
/// Should be set to floating point value between 2 and 4
/// Fixes issues on Heltec v2
var adcMultiplierOverride: Float = 0
///
/// Wait Bluetooth Seconds
/// The number of seconds for to wait before turning of BLE in No Bluetooth states\
/// The number of seconds for to wait before turning off BLE in No Bluetooth states
/// 0 for default of 1 minute
var waitBluetoothSecs: UInt32 = 0
@ -425,7 +412,7 @@ struct Config {
/// Light Sleep Seconds
/// In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
/// ESP32 Only
/// 0 for default of 3600
/// 0 for default of 300
var lsSecs: UInt32 = 0
///
@ -441,73 +428,22 @@ struct Config {
/// **TBEAM 1.1 Only**
enum ChargeCurrent: SwiftProtobuf.Enum {
typealias RawValue = Int
///
/// TODO: REPLACE
case maunset // = 0
///
/// TODO: REPLACE
case ma100 // = 1
///
/// TODO: REPLACE
case ma190 // = 2
///
/// TODO: REPLACE
case ma280 // = 3
///
/// TODO: REPLACE
case ma360 // = 4
///
/// TODO: REPLACE
case ma450 // = 5
///
/// TODO: REPLACE
case ma550 // = 6
///
/// TODO: REPLACE
case ma630 // = 7
///
/// TODO: REPLACE
case ma700 // = 8
///
/// TODO: REPLACE
case ma780 // = 9
///
/// TODO: REPLACE
case ma880 // = 10
///
/// TODO: REPLACE
case ma960 // = 11
///
/// TODO: REPLACE
case ma1000 // = 12
///
/// TODO: REPLACE
case ma1080 // = 13
///
/// TODO: REPLACE
case ma1160 // = 14
///
/// TODO: REPLACE
case ma1240 // = 15
///
/// TODO: REPLACE
case ma1320 // = 16
case UNRECOGNIZED(Int)
@ -567,7 +503,7 @@ struct Config {
}
///
/// TODO: REPLACE
/// WiFi Config
struct WiFiConfig {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
@ -604,13 +540,12 @@ struct Config {
// methods supported on all messages.
///
/// Power management state machine option.
/// See [power management](/docs/software/other/power) for details.
/// 0 for default of one minute
/// Number of seconds the screen stays on after pressing the user button or receiving a message
/// 0 for default of one minute MAXUINT for always on
var screenOnSecs: UInt32 = 0
///
/// How the GPS coordinates are displayed on the OLED screen.
/// How the GPS coordinates are formatted on the OLED screen.
var gpsFormat: Config.DisplayConfig.GpsCoordinateFormat = .gpsFormatDec
///
@ -636,24 +571,24 @@ struct Config {
case gpsFormatDms // = 1
///
/// GPS coordinates are displayed in Universal Transverse Mercator format:
/// 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:
/// 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).
/// 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
/// 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)
@ -691,7 +626,7 @@ struct Config {
}
///
/// TODO: REPLACE
/// Lora Config
struct LoRaConfig {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
@ -705,7 +640,6 @@ struct Config {
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.
@ -736,11 +670,12 @@ struct Config {
var frequencyOffset: Float = 0
///
/// The region code for my radio (US, CN, EU433, etc...)
/// The region code for the radio (US, CN, EU433, etc...)
var region: Config.LoRaConfig.RegionCode = .unset
///
/// Overrides HOPS_RELIABLE and sets the maximum number of hops. This can't be greater than 7.
/// 0 for default of 3
var hopLimit: UInt32 = 0
///
@ -756,66 +691,59 @@ struct Config {
var unknownFields = SwiftProtobuf.UnknownStorage()
///
/// 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
///
/// TODO: REPLACE
/// Region is not set
case unset // = 0
///
/// TODO: REPLACE
/// United States
case us // = 1
///
/// TODO: REPLACE
/// European Union 433mhz
case eu433 // = 2
///
/// TODO: REPLACE
/// European Union 433mhz
case eu868 // = 3
///
/// TODO: REPLACE
/// China
case cn // = 4
///
/// TODO: REPLACE
/// Japan
case jp // = 5
///
/// TODO: REPLACE
/// Australia / New Zealand
case anz // = 6
///
/// TODO: REPLACE
/// Korea
case kr // = 7
///
/// TODO: REPLACE
/// Taiwan
case tw // = 8
///
/// TODO: REPLACE
/// Russia
case ru // = 9
///
/// TODO: REPLACE
/// India
case `in` // = 10
///
/// TODO: REPLACE
/// New Zealand 865mhz
case nz865 // = 11
///
/// TODO: REPLACE
/// Thailand
case th // = 12
case UNRECOGNIZED(Int)
@ -870,31 +798,31 @@ struct Config {
typealias RawValue = Int
///
/// TODO: REPLACE
/// Long Range - Fast
case longFast // = 0
///
/// TODO: REPLACE
/// Long Range - Slow
case longSlow // = 1
///
/// TODO: REPLACE
/// Very Long Range - Slow
case vlongSlow // = 2
///
/// TODO: REPLACE
/// Medium Range - Slow
case midSlow // = 3
///
/// TODO: REPLACE
/// Medium Range - Fast
case midFast // = 4
///
/// TODO: REPLACE
/// Short Range - Slow
case shortSlow // = 5
///
/// TODO: REPLACE
/// Short Range - Fast
case shortFast // = 6
case UNRECOGNIZED(Int)
@ -960,6 +888,8 @@ extension Config.PositionConfig.PositionFlags: CaseIterable {
.posSatinview,
.posSeqNos,
.posTimestamp,
.posHeading,
.posSpeed,
]
}
@ -1337,6 +1267,8 @@ extension Config.PositionConfig.PositionFlags: SwiftProtobuf._ProtoNameProviding
32: .same(proto: "POS_SATINVIEW"),
64: .same(proto: "POS_SEQ_NOS"),
128: .same(proto: "POS_TIMESTAMP"),
256: .same(proto: "POS_HEADING"),
512: .same(proto: "POS_SPEED"),
]
}

View file

@ -22,7 +22,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
case .client:
return "Client (default)"
case .clientMute:
return "Client Mute - Packets will not hop over this node, does not contribute to routing packets for mesh."
return "Client Mute - Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh."
case .router:
return "Router - Mesh packets will prefer to be routed over this node. This node will not be used by client apps. The wifi/ble radios and the oled screen will be put to sleep."
case .routerClient:

View file

@ -28,7 +28,7 @@ enum RegionCodes : Int, CaseIterable, Identifiable {
get {
switch self {
case .unset:
return "UNSET - Please set a Region"
return "Please set a region"
case .us:
return "United States"
case .eu433:
@ -107,19 +107,19 @@ enum ModemPresets : Int, CaseIterable, Identifiable {
switch self {
case .LongFast:
return "Long Fast"
return "Long Range - Fast"
case .LongSlow:
return "Long Slow"
return "Long Range - Slow"
case .VLongSlow:
return "Very Long Slow"
return "Very Long Range - Slow"
case .MidSlow:
return "Mid Slow"
return "Medium Range - Slow"
case .MidFast:
return "Mid Fast"
return "Medium Range - Fast"
case .ShortSlow:
return "Short Slow"
return "Short Range - Slow"
case .ShortFast:
return "Short Fast"
return "Short Range - Fast"
}
}
}
@ -146,12 +146,48 @@ enum ModemPresets : Int, CaseIterable, Identifiable {
}
}
enum HopValues : Int, CaseIterable, Identifiable {
case oneHop = 1
case twoHops = 2
case threeHops = 0
case fourHops = 4
case fiveHops = 5
case sixHops = 6
case sevenHops = 7
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .oneHop:
return "One Hop"
case .twoHops:
return "Two Hops"
case .threeHops:
return "Three Hops"
case .fourHops:
return "Four Hops"
case .fiveHops:
return "Five Hops"
case .sixHops:
return "Six Hops"
case .sevenHops:
return "Seven Hops"
}
}
}
}
struct LoRaConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State var region = 1
@State private var isPresentingSaveConfirm: Bool = false
@State var region = 0
@State var modemPreset = 0
@State var hopLimit = 0
@State var hasChanges = false
@ -169,10 +205,9 @@ struct LoRaConfig: View {
}
}
.pickerStyle(DefaultPickerStyle())
Text("The region where you will be using your Meshtastic LoRa radios.")
Text("The region where you will be using your radios.")
.font(.caption)
.listRowSeparator(.visible)
.listRowSeparator(.visible)
}
Section(header: Text("Modem")) {
Picker("Presets", selection: $region ) {
@ -181,38 +216,27 @@ struct LoRaConfig: View {
}
}
.pickerStyle(DefaultPickerStyle())
Text("Available modem presets.")
Text("Available modem presets, default is Long Fast.")
.font(.caption)
.listRowSeparator(.visible)
.listRowSeparator(.visible)
}
Section(header: Text("Mesh Options")) {
Picker("Number of hops", selection: $hopLimit) {
ForEach(0..<8) {
if $0 == 0 {
Text("Default")
} else {
Text("\($0) Hops")
}
ForEach(HopValues.allCases) { hop in
Text(hop.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("Sets the maximum number of hops, default is 3.")
.font(.caption)
.listRowSeparator(.visible)
}
}
Button {
var lc = Config.LoRaConfig()
lc.hopLimit = UInt32(hopLimit)
lc.region = RegionCodes(rawValue: region)!.protoEnumValue()
lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue()
if bleManager.saveLoRaConfig(config: lc, destNum: bleManager.connectedPeripheral.num, wantResponse: false) {
} else {
}
isPresentingSaveConfirm = true
} label: {
Label("Save", systemImage: "square.and.arrow.down")
@ -222,6 +246,28 @@ struct LoRaConfig: View {
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
.confirmationDialog(
"Are you sure?",
isPresented: $isPresentingSaveConfirm
) {
Button("Save LoRa Config to device?") {
var lc = Config.LoRaConfig()
lc.hopLimit = UInt32(hopLimit)
lc.region = RegionCodes(rawValue: region)!.protoEnumValue()
lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue()
if bleManager.saveLoRaConfig(config: lc, destNum: bleManager.connectedPeripheral.num, wantResponse: false) {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
} else {
}
}
}
}
.navigationTitle("LoRa Config")
@ -235,7 +281,7 @@ struct LoRaConfig: View {
self.bleManager.context = context
}
.onChange(of: region) { newRegion in
.onChange(of: region) { newModemPreset in
hasChanges = true
}

View file

@ -118,8 +118,14 @@ struct PositionConfig: View {
@State var gpsAttemptTime = 0
@State var positionBroadcastSeconds = 0
@State var includeAltitude = false
@State var includeSatInView = false
@State var includePosAltitude = false
@State var includePosSatsinview = false
@State var includePosSeqNos = false
@State var includePosTimestamp = false
@State var includePosSpeed = false
@State var includePosHeading = false
var body: some View {
@ -203,30 +209,44 @@ struct PositionConfig: View {
.font(.caption)
.listRowSeparator(.visible)
Toggle(isOn: $includeAltitude) {
Toggle(isOn: $includePosAltitude) {
Label("Include Altitude", systemImage: "arrow.up")
Label("Altitude", systemImage: "arrow.up")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)
Toggle(isOn: $includeSatInView) {
Toggle(isOn: $includePosSatsinview) {
Label("Include number of satellites in view", systemImage: "skew")
Label("Number of satellites", systemImage: "skew")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)
Toggle(isOn: $includeSatInView) { //64
Toggle(isOn: $includePosSeqNos) { //64
Label("Include a sequence number incremented per packet", systemImage: "number")
Label("Sequence number", systemImage: "number")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)
Toggle(isOn: $includeSatInView) { //128
Toggle(isOn: $includePosTimestamp) { //128
Label("Include positional timestamp", systemImage: "clock")
Label("Timestamp", systemImage: "clock")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)
Toggle(isOn: $includePosHeading) { //128
Label("Vehicle heading", systemImage: "location.circle")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)
Toggle(isOn: $includePosSpeed) { //128
Label("Vehicle speed", systemImage: "speedometer")
}
.toggleStyle(DefaultToggleStyle())
.listRowSeparator(.visible)