From 22671a73db7c4fe8d257610ef468fbbd0fd890a4 Mon Sep 17 00:00:00 2001 From: andrekir Date: Wed, 12 Oct 2022 23:40:54 -0300 Subject: [PATCH 1/5] detect UUID to warn firmware is too old --- .../main/java/com/geeksville/mesh/MainActivity.kt | 4 ++++ .../mesh/repository/radio/BluetoothInterface.kt | 13 ++++++++++++- .../java/com/geeksville/mesh/service/MeshService.kt | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) 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/repository/radio/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt index d77dab876..9d57100c0 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,13 @@ 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 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 { From 868a0f7bd31b05b7ce898acc0dc58d81b7f63d17 Mon Sep 17 00:00:00 2001 From: andrekir Date: Thu, 13 Oct 2022 00:02:00 -0300 Subject: [PATCH 2/5] reset invalidVersion just in case --- .../geeksville/mesh/repository/radio/BluetoothInterface.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 9d57100c0..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 @@ -366,7 +366,10 @@ class BluetoothInterface( .contains(EOL_FROMRADIO_CHARACTER)) { invalidVersion = true getCharacteristic(EOL_FROMRADIO_CHARACTER) - } else getCharacteristic(BTM_FROMRADIO_CHARACTER) + } else { + invalidVersion = false + getCharacteristic(BTM_FROMRADIO_CHARACTER) + } // We treat the first send by a client as special isFirstSend = true From 2e4cae048f3ce71e951175a981d80738d8094daf Mon Sep 17 00:00:00 2001 From: andrekir Date: Thu, 13 Oct 2022 00:18:19 -0300 Subject: [PATCH 3/5] update QR code convention --- app/src/main/AndroidManifest.xml | 6 +++--- app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt | 4 ++-- .../test/java/com/geeksville/mesh/model/ChannelSetTest.kt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) 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/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/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) From 003da7c37ac6bd1d055f70454ba8de72770307b5 Mon Sep 17 00:00:00 2001 From: andrekir Date: Thu, 13 Oct 2022 00:29:22 -0300 Subject: [PATCH 4/5] 1.3.43 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From f310bb20197db22718975934786b69c0fbc57bdb Mon Sep 17 00:00:00 2001 From: andrekir Date: Thu, 13 Oct 2022 18:20:51 -0300 Subject: [PATCH 5/5] change ModemPreset and don't reset LoRaConfig --- .../main/java/com/geeksville/mesh/ui/ChannelFragment.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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