kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Merge branch 'meshtastic:master' into osmdroid-phase3
commit
4acbd05472
|
@ -43,8 +43,8 @@ android {
|
||||||
applicationId "com.geeksville.mesh"
|
applicationId "com.geeksville.mesh"
|
||||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 20342 // format is Mmmss (where M is 1+the numeric major number
|
versionCode 20343 // format is Mmmss (where M is 1+the numeric major number
|
||||||
versionName "1.3.42"
|
versionName "1.3.43"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// per https://developer.android.com/studio/write/vector-asset-studio
|
// per https://developer.android.com/studio/write/vector-asset-studio
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
<!-- The QR codes to share channel settings are shared as meshtastic URLS
|
<!-- The QR codes to share channel settings are shared as meshtastic URLS
|
||||||
|
|
||||||
an approximate example:
|
an approximate example:
|
||||||
http://www.meshtastic.org/e/YXNkZnF3ZXJhc2RmcXdlcmFzZGZxd2Vy
|
http://meshtastic.org/e/YXNkZnF3ZXJhc2RmcXdlcmFzZGZxd2Vy
|
||||||
-->
|
-->
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
@ -146,11 +146,11 @@
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:scheme="https"
|
android:scheme="https"
|
||||||
android:host="www.meshtastic.org"
|
android:host="meshtastic.org"
|
||||||
android:pathPrefix="/e/" />
|
android:pathPrefix="/e/" />
|
||||||
<data
|
<data
|
||||||
android:scheme="https"
|
android:scheme="https"
|
||||||
android:host="www.meshtastic.org"
|
android:host="meshtastic.org"
|
||||||
android:pathPrefix="/E/" />
|
android:pathPrefix="/E/" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ import com.geeksville.mesh.model.BluetoothViewModel
|
||||||
import com.geeksville.mesh.model.ChannelSet
|
import com.geeksville.mesh.model.ChannelSet
|
||||||
import com.geeksville.mesh.model.DeviceVersion
|
import com.geeksville.mesh.model.DeviceVersion
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
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.RadioInterfaceService
|
||||||
import com.geeksville.mesh.repository.radio.SerialInterface
|
import com.geeksville.mesh.repository.radio.SerialInterface
|
||||||
import com.geeksville.mesh.service.*
|
import com.geeksville.mesh.service.*
|
||||||
|
@ -416,6 +417,7 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
|
|
||||||
/** Show an alert that may contain HTML */
|
/** Show an alert that may contain HTML */
|
||||||
private fun showAlert(titleText: Int, messageText: Int) {
|
private fun showAlert(titleText: Int, messageText: Int) {
|
||||||
|
|
||||||
// make links clickable per https://stackoverflow.com/a/62642807
|
// make links clickable per https://stackoverflow.com/a/62642807
|
||||||
// val messageStr = getText(messageText)
|
// 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) {
|
} catch (ex: RemoteException) {
|
||||||
warn("Abandoning connect $ex, because we probably just lost device connection")
|
warn("Abandoning connect $ex, because we probably just lost device connection")
|
||||||
|
|
|
@ -15,7 +15,7 @@ data class ChannelSet(
|
||||||
) : Logging {
|
) : Logging {
|
||||||
companion object {
|
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
|
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
|
// We encode as UPPER case for the QR code URL because QR codes are more efficient for that special case
|
||||||
val bitMatrix =
|
val bitMatrix =
|
||||||
multiFormatWriter.encode(
|
multiFormatWriter.encode(
|
||||||
getChannelUrl(true).toString(),
|
getChannelUrl(false).toString(),
|
||||||
BarcodeFormat.QR_CODE,
|
BarcodeFormat.QR_CODE,
|
||||||
960,
|
960,
|
||||||
960
|
960
|
||||||
|
|
|
@ -99,6 +99,10 @@ class BluetoothInterface(
|
||||||
/// this service UUID is publically visible for scanning
|
/// this service UUID is publically visible for scanning
|
||||||
val BTM_SERVICE_UUID: UUID = UUID.fromString("6ba1b218-15a8-461f-9fa8-5dcae273eafd")
|
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 =
|
val BTM_FROMRADIO_CHARACTER: UUID =
|
||||||
UUID.fromString("2c55e69e-4993-11ed-b878-0242ac120002")
|
UUID.fromString("2c55e69e-4993-11ed-b878-0242ac120002")
|
||||||
val BTM_TORADIO_CHARACTER: UUID =
|
val BTM_TORADIO_CHARACTER: UUID =
|
||||||
|
@ -149,6 +153,7 @@ class BluetoothInterface(
|
||||||
?: throw RadioNotConnectedException("BLE service not found")
|
?: throw RadioNotConnectedException("BLE service not found")
|
||||||
|
|
||||||
private lateinit var fromNum: BluetoothGattCharacteristic
|
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,
|
* 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
|
/// Attempt to read from the fromRadio mailbox, if data is found broadcast it to android apps
|
||||||
private fun doReadFromRadio(firstRead: Boolean) {
|
private fun doReadFromRadio(firstRead: Boolean) {
|
||||||
safe?.let { s ->
|
safe?.let { s ->
|
||||||
val fromRadio = getCharacteristic(BTM_FROMRADIO_CHARACTER)
|
|
||||||
s.asyncReadCharacteristic(fromRadio) {
|
s.asyncReadCharacteristic(fromRadio) {
|
||||||
try {
|
try {
|
||||||
val b = it.getOrThrow()
|
val b = it.getOrThrow()
|
||||||
|
@ -357,6 +361,16 @@ class BluetoothInterface(
|
||||||
|
|
||||||
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
|
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
|
// We treat the first send by a client as special
|
||||||
isFirstSend = true
|
isFirstSend = true
|
||||||
|
|
||||||
|
|
|
@ -1391,6 +1391,9 @@ class MeshService : Service(), Logging {
|
||||||
configNonce += 1
|
configNonce += 1
|
||||||
newNodes.clear()
|
newNodes.clear()
|
||||||
newMyNodeInfo = null
|
newMyNodeInfo = null
|
||||||
|
|
||||||
|
if (BluetoothInterface.invalidVersion) onHasSettings() // Device firmware is too old
|
||||||
|
|
||||||
debug("Starting config nonce=$configNonce")
|
debug("Starting config nonce=$configNonce")
|
||||||
|
|
||||||
sendToRadio(ToRadio.newBuilder().apply {
|
sendToRadio(ToRadio.newBuilder().apply {
|
||||||
|
|
|
@ -313,12 +313,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
// No matter what apply the speed selection from the user
|
// No matter what apply the speed selection from the user
|
||||||
val newLoRaConfig = loRaConfig {
|
val newLoRaConfig = model.config.lora.copy {
|
||||||
usePreset = true
|
usePreset = true
|
||||||
modemPreset = newModemPreset
|
modemPreset = newModemPreset
|
||||||
region = model.region
|
bandwidth = 0
|
||||||
txEnabled = model.txEnabled
|
spreadFactor = 0
|
||||||
txPower = model.config.lora.txPower
|
codingRate = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
val humanName = Channel(newSettings, newLoRaConfig).humanName
|
val humanName = Channel(newSettings, newLoRaConfig).humanName
|
||||||
|
|
|
@ -8,7 +8,7 @@ class ChannelSetTest {
|
||||||
/** make sure we match the python and device code behavior */
|
/** make sure we match the python and device code behavior */
|
||||||
@Test
|
@Test
|
||||||
fun matchPython() {
|
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)
|
val cs = ChannelSet(url)
|
||||||
Assert.assertEquals("LongFast", cs.primaryChannel!!.name)
|
Assert.assertEquals("LongFast", cs.primaryChannel!!.name)
|
||||||
Assert.assertEquals("#LongFast-K", cs.primaryChannel!!.humanName)
|
Assert.assertEquals("#LongFast-K", cs.primaryChannel!!.humanName)
|
||||||
|
|
Ładowanie…
Reference in New Issue