diff --git a/app/build.gradle b/app/build.gradle
index 49e8b7a97..9f8ea3398 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -43,8 +43,8 @@ android {
applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 30
- versionCode 20342 // format is Mmmss (where M is 1+the numeric major number
- versionName "1.3.42"
+ versionCode 20343 // format is Mmmss (where M is 1+the numeric major number
+ versionName "1.3.43"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// per https://developer.android.com/studio/write/vector-asset-studio
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 535d6953d..bbd202024 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -137,7 +137,7 @@
@@ -146,11 +146,11 @@
diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
index 0ec7b5716..8d728cd34 100644
--- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt
+++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
@@ -40,6 +40,7 @@ import com.geeksville.mesh.model.BluetoothViewModel
import com.geeksville.mesh.model.ChannelSet
import com.geeksville.mesh.model.DeviceVersion
import com.geeksville.mesh.model.UIViewModel
+import com.geeksville.mesh.repository.radio.BluetoothInterface
import com.geeksville.mesh.repository.radio.RadioInterfaceService
import com.geeksville.mesh.repository.radio.SerialInterface
import com.geeksville.mesh.service.*
@@ -416,6 +417,7 @@ class MainActivity : BaseActivity(), Logging {
/** Show an alert that may contain HTML */
private fun showAlert(titleText: Int, messageText: Int) {
+
// make links clickable per https://stackoverflow.com/a/62642807
// val messageStr = getText(messageText)
@@ -476,6 +478,8 @@ class MainActivity : BaseActivity(), Logging {
}
}
}
+ } else if (BluetoothInterface.invalidVersion) {
+ showAlert(R.string.firmware_too_old, R.string.firmware_old)
}
} catch (ex: RemoteException) {
warn("Abandoning connect $ex, because we probably just lost device connection")
diff --git a/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt b/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt
index 9789bdb13..3d6a6c356 100644
--- a/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt
+++ b/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt
@@ -15,7 +15,7 @@ data class ChannelSet(
) : Logging {
companion object {
- const val prefix = "https://www.meshtastic.org/e/#"
+ const val prefix = "https://meshtastic.org/e/#"
private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING
@@ -65,7 +65,7 @@ data class ChannelSet(
// We encode as UPPER case for the QR code URL because QR codes are more efficient for that special case
val bitMatrix =
multiFormatWriter.encode(
- getChannelUrl(true).toString(),
+ getChannelUrl(false).toString(),
BarcodeFormat.QR_CODE,
960,
960
diff --git a/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt
index d77dab876..3c843a9c7 100644
--- a/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt
+++ b/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt
@@ -99,6 +99,10 @@ class BluetoothInterface(
/// this service UUID is publically visible for scanning
val BTM_SERVICE_UUID: UUID = UUID.fromString("6ba1b218-15a8-461f-9fa8-5dcae273eafd")
+ var invalidVersion = false
+ val EOL_FROMRADIO_CHARACTER: UUID =
+ UUID.fromString("8ba2bcc2-ee02-4a55-a531-c525c5e454d5")
+
val BTM_FROMRADIO_CHARACTER: UUID =
UUID.fromString("2c55e69e-4993-11ed-b878-0242ac120002")
val BTM_TORADIO_CHARACTER: UUID =
@@ -149,6 +153,7 @@ class BluetoothInterface(
?: throw RadioNotConnectedException("BLE service not found")
private lateinit var fromNum: BluetoothGattCharacteristic
+ private lateinit var fromRadio: BluetoothGattCharacteristic
/**
* With the new rev2 api, our first send is to start the configure readbacks. In that case,
@@ -228,7 +233,6 @@ class BluetoothInterface(
/// Attempt to read from the fromRadio mailbox, if data is found broadcast it to android apps
private fun doReadFromRadio(firstRead: Boolean) {
safe?.let { s ->
- val fromRadio = getCharacteristic(BTM_FROMRADIO_CHARACTER)
s.asyncReadCharacteristic(fromRadio) {
try {
val b = it.getOrThrow()
@@ -357,6 +361,16 @@ class BluetoothInterface(
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
+ // We changed UUIDs to be able to identify old firmware (<1.3.43)
+ fromRadio = if (bservice.characteristics.map { it.uuid }
+ .contains(EOL_FROMRADIO_CHARACTER)) {
+ invalidVersion = true
+ getCharacteristic(EOL_FROMRADIO_CHARACTER)
+ } else {
+ invalidVersion = false
+ getCharacteristic(BTM_FROMRADIO_CHARACTER)
+ }
+
// We treat the first send by a client as special
isFirstSend = true
diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
index dbb34d822..66de2ef58 100644
--- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
+++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
@@ -1391,6 +1391,9 @@ class MeshService : Service(), Logging {
configNonce += 1
newNodes.clear()
newMyNodeInfo = null
+
+ if (BluetoothInterface.invalidVersion) onHasSettings() // Device firmware is too old
+
debug("Starting config nonce=$configNonce")
sendToRadio(ToRadio.newBuilder().apply {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
index a04cbc066..5684be78a 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt
@@ -313,12 +313,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
}
// No matter what apply the speed selection from the user
- val newLoRaConfig = loRaConfig {
+ val newLoRaConfig = model.config.lora.copy {
usePreset = true
modemPreset = newModemPreset
- region = model.region
- txEnabled = model.txEnabled
- txPower = model.config.lora.txPower
+ bandwidth = 0
+ spreadFactor = 0
+ codingRate = 0
}
val humanName = Channel(newSettings, newLoRaConfig).humanName
diff --git a/app/src/test/java/com/geeksville/mesh/model/ChannelSetTest.kt b/app/src/test/java/com/geeksville/mesh/model/ChannelSetTest.kt
index 524b23ff0..a70c0bbd8 100644
--- a/app/src/test/java/com/geeksville/mesh/model/ChannelSetTest.kt
+++ b/app/src/test/java/com/geeksville/mesh/model/ChannelSetTest.kt
@@ -8,7 +8,7 @@ class ChannelSetTest {
/** make sure we match the python and device code behavior */
@Test
fun matchPython() {
- val url = Uri.parse("https://www.meshtastic.org/e/#CgUYAiIBAQ")
+ val url = Uri.parse("https://meshtastic.org/e/#CgUYAiIBAQ")
val cs = ChannelSet(url)
Assert.assertEquals("LongFast", cs.primaryChannel!!.name)
Assert.assertEquals("#LongFast-K", cs.primaryChannel!!.humanName)