mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #127 from meshtastic/feature/module_settings
Lora config cleanup
This commit is contained in:
commit
706274411e
9 changed files with 178 additions and 81 deletions
|
|
@ -1169,6 +1169,55 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func getCannedMessageModuleMessages(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.getCannedMessageModulePart1Request = true
|
||||
|
||||
//adminPacket.getOwnerRequest = true
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
do {
|
||||
|
||||
try context!.save()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("💾 Saved a Canned Messages Module Get Messages Request Admin Message for node: \(String(destNum))") }
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
return true
|
||||
|
||||
} catch {
|
||||
|
||||
context!.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Inserting New Core Data MessageEntity: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public func saveExternalNotificationModuleConfig(config: ModuleConfig.ExternalNotificationConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
|
|
|
|||
|
|
@ -190,14 +190,16 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
newLoRaConfig.modemPreset = 0
|
||||
// 3 Hops default protobuf value of 0
|
||||
newLoRaConfig.hopLimit = 0
|
||||
// Default value of 0 is 22dbm
|
||||
newLoRaConfig.txPower = 0
|
||||
|
||||
} else {
|
||||
|
||||
// UNSET default protobuf value of 0
|
||||
newLoRaConfig.regionCode = Int32(config.lora.region.rawValue)
|
||||
// LongFast default protobuf value of 0
|
||||
newLoRaConfig.modemPreset = Int32(config.lora.modemPreset.rawValue)
|
||||
// 3 Hops default protobuf value of 0
|
||||
newLoRaConfig.hopLimit = Int32(config.lora.hopLimit)
|
||||
newLoRaConfig.txPower = Int32(config.lora.txPower)
|
||||
|
||||
}
|
||||
|
||||
fetchedNode[0].loRaConfig = newLoRaConfig
|
||||
|
|
@ -212,14 +214,15 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
fetchedNode[0].loRaConfig?.modemPreset = 0
|
||||
// 3 Hops default protobuf value of 0
|
||||
fetchedNode[0].loRaConfig?.hopLimit = 0
|
||||
// Default value of 0 is 22dbm
|
||||
fetchedNode[0].loRaConfig?.txPower = 0
|
||||
|
||||
} else {
|
||||
// UNSET default protobuf value of 0
|
||||
|
||||
fetchedNode[0].loRaConfig?.regionCode = Int32(config.lora.region.rawValue)
|
||||
// LongFast default protobuf value of 0
|
||||
fetchedNode[0].loRaConfig?.modemPreset = Int32(config.lora.modemPreset.rawValue)
|
||||
// 3 Hops default protobuf value of 0
|
||||
fetchedNode[0].loRaConfig?.hopLimit = Int32(config.lora.hopLimit)
|
||||
fetchedNode[0].loRaConfig?.txPower = Int32(config.lora.txPower)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +420,7 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
|
||||
try context.save()
|
||||
if meshlogging { MeshLogger.log("💾 Updated Canned Message Module Config for node number: \(String(nodeNum))") }
|
||||
print(try config.cannedMessage.jsonString())
|
||||
|
||||
} catch {
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
|
|
@ -175,6 +176,7 @@
|
|||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
|
|
@ -196,7 +198,7 @@
|
|||
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="104"/>
|
||||
<element name="ExternalNotificationConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="230"/>
|
||||
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
|
||||
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="299"/>
|
||||
|
|
@ -206,6 +208,6 @@
|
|||
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
|
||||
<element name="TelemetryConfigEntity" positionX="72" positionY="171" width="128" height="179"/>
|
||||
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="209"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="215"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="230"/>
|
||||
</elements>
|
||||
</model>
|
||||
|
|
@ -146,7 +146,7 @@ struct Connect: View {
|
|||
|
||||
if bleManager.peripherals.count > 0 {
|
||||
Section(header: Text("Available Radios").font(.title)) {
|
||||
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name < $1.name })) { peripheral in
|
||||
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.rssi > $1.rssi })) { peripheral in
|
||||
HStack {
|
||||
Image(systemName: "circle.fill")
|
||||
.imageScale(.large).foregroundColor(.gray)
|
||||
|
|
|
|||
|
|
@ -225,7 +225,16 @@ struct UserMessageList: View {
|
|||
VStack {
|
||||
|
||||
let ackDate = Date(timeIntervalSince1970: TimeInterval(message.ackTimestamp))
|
||||
Text("ACK \(ackDate, style: .date) \(ackDate, style: .time)").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
|
||||
if ackDate >= sixMonthsAgo! {
|
||||
|
||||
Text("ACK \(ackDate, style: .date) \(ackDate, style: .time)").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else {
|
||||
|
||||
Text("Unknown Age").font(.caption2).foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
if message.ackSNR != 0 {
|
||||
|
|
|
|||
|
|
@ -79,10 +79,12 @@ struct NodeDetail: View {
|
|||
ScrollView {
|
||||
|
||||
if self.bleManager.connectedPeripheral != nil && self.bleManager.connectedPeripheral.num == node.num && self.bleManager.connectedPeripheral.num == node.num {
|
||||
|
||||
Divider()
|
||||
HStack {
|
||||
|
||||
if hwModelString == "TBEAM" || hwModelString == "TECHO" || hwModelString.contains("4631") {
|
||||
|
||||
|
||||
Button(action: {
|
||||
|
||||
isPresentingShutdownConfirm = true
|
||||
|
|
@ -136,7 +138,6 @@ struct NodeDetail: View {
|
|||
}
|
||||
}
|
||||
.padding(5)
|
||||
Divider()
|
||||
}
|
||||
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ struct TelemetryLog: View {
|
|||
|
||||
let sensor = SensorTypes(rawValue: Int(node.telemetryConfig?.environmentSensorType ?? 0))
|
||||
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°F" : "°C"
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°C" : "°F"
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
|
|
@ -178,8 +178,9 @@ struct TelemetryLog: View {
|
|||
|
||||
if tel.metricsType == 0 {
|
||||
|
||||
// Device Metrics
|
||||
// Device Metrics iPhone Template
|
||||
VStack {
|
||||
|
||||
HStack {
|
||||
|
||||
Spacer()
|
||||
|
|
@ -243,94 +244,121 @@ struct TelemetryLog: View {
|
|||
// Environment Metrics
|
||||
let sensor = SensorTypes(rawValue: Int(node.telemetryConfig?.environmentSensorType ?? 0))
|
||||
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°F" : "°C"
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°C" : "°F"
|
||||
|
||||
|
||||
// Environment Metrics iPhone Template
|
||||
VStack {
|
||||
|
||||
Text("Environment Metrics")
|
||||
.font(.title3)
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 ||
|
||||
sensor == SensorTypes.mcp9808 {
|
||||
HStack {
|
||||
|
||||
Image(systemName: "thermometer")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Temperature: \(String(format: "%.2f", tel.temperature))\(tempReadingType)")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
Spacer()
|
||||
Text("Environment Metrics")
|
||||
.font(.title3)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 {
|
||||
|
||||
Image(systemName: "humidity")
|
||||
|
||||
HStack {
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 ||
|
||||
sensor == SensorTypes.mcp9808 {
|
||||
|
||||
Image(systemName: "thermometer")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Temperature: \(String(format: "%.2f", tel.temperature))\(tempReadingType)")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Relative Humidity: \(String(format: "%.2f", tel.relativeHumidity))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 {
|
||||
|
||||
Image(systemName: "humidity")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Relative Humidity: \(String(format: "%.2f", tel.relativeHumidity))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.ina219 ||
|
||||
sensor == SensorTypes.ina260 {
|
||||
|
||||
Image(systemName: "directcurrent")
|
||||
HStack {
|
||||
|
||||
Image(systemName: "directcurrent")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Current: \(String(format: "%.2f", tel.current))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Current: \(String(format: "%.2f", tel.current))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
Image(systemName: "bolt")
|
||||
HStack {
|
||||
|
||||
Image(systemName: "bolt")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Voltage: \(String(format: "%.2f", tel.voltage))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Voltage: \(String(format: "%.2f", tel.voltage))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 {
|
||||
|
||||
Image(systemName: "barometer")
|
||||
HStack {
|
||||
|
||||
Image(systemName: "barometer")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Barometric Pressure: \(String(format: "%.2f", tel.barometricPressure))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Barometric Pressure: \(String(format: "%.2f", tel.barometricPressure))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme680 {
|
||||
|
||||
Image(systemName: "aqi.medium")
|
||||
HStack {
|
||||
|
||||
Image(systemName: "aqi.medium")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Gas Resistance: \(String(format: "%.2f", tel.gasResistance))")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
|
||||
Image(systemName: "clock.badge.checkmark.fill")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Gas Resistance: \(String(format: "%.2f", tel.gasResistance))")
|
||||
Text("Time:")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
DateTimeText(dateTime: tel.time)
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
}
|
||||
|
||||
Image(systemName: "clock.badge.checkmark.fill")
|
||||
.font(.callout)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Time:")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
DateTimeText(dateTime: tel.time)
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ enum RegionCodes : Int, CaseIterable, Identifiable {
|
|||
case tw = 8
|
||||
case ru = 9
|
||||
case `in` = 10
|
||||
case nz865
|
||||
case th
|
||||
case nz865 = 11
|
||||
case th = 12
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
|
|
@ -187,13 +187,14 @@ struct LoRaConfig: View {
|
|||
|
||||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var isPresentingSaveConfirm = false
|
||||
@State var initialLoad = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var region = 0
|
||||
@State var modemPreset = 0
|
||||
@State var hopLimit = 0
|
||||
@State var txPower = 0
|
||||
|
||||
var body: some View {
|
||||
|
||||
|
|
@ -210,7 +211,6 @@ struct LoRaConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("The region where you will be using your radios.")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
Section(header: Text("Modem")) {
|
||||
Picker("Presets", selection: $modemPreset ) {
|
||||
|
|
@ -221,7 +221,6 @@ struct LoRaConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("Available modem presets, default is Long Fast.")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
Section(header: Text("Mesh Options")) {
|
||||
|
||||
|
|
@ -233,10 +232,9 @@ struct LoRaConfig: View {
|
|||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("Sets the maximum number of hops, default is 3. Increasing hops also increases air time utilization and should be used carefully.")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
}
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
.disabled(self.bleManager.connectedPeripheral == nil)
|
||||
|
||||
Button {
|
||||
|
||||
|
|
@ -286,13 +284,16 @@ struct LoRaConfig: View {
|
|||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.hopLimit = Int(node!.loRaConfig?.hopLimit ?? 0)
|
||||
self.region = Int(node!.loRaConfig?.regionCode ?? 0)
|
||||
self.modemPreset = Int(node!.loRaConfig?.modemPreset ?? 0)
|
||||
self.txPower = Int(node!.loRaConfig?.txPower ?? 0)
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,6 +362,9 @@ struct CannedMessagesConfig: View {
|
|||
self.inputbrokerPinA = Int(node!.cannedMessageConfig?.inputbrokerPinA ?? 0)
|
||||
self.inputbrokerPinB = Int(node!.cannedMessageConfig?.inputbrokerPinB ?? 0)
|
||||
self.inputbrokerPinPress = Int(node!.cannedMessageConfig?.inputbrokerPinPress ?? 0)
|
||||
self.inputbrokerEventCw = Int(node!.cannedMessageConfig?.inputbrokerEventCw ?? 0)
|
||||
self.inputbrokerEventCcw = Int(node!.cannedMessageConfig?.inputbrokerEventCcw ?? 0)
|
||||
self.inputbrokerEventPress = Int(node!.cannedMessageConfig?.inputbrokerEventPress ?? 0)
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue