Merge pull request #81 from geeksville/dev

Dev
pull/85/head
Kevin Hester 2020-07-02 10:43:14 -07:00 zatwierdzone przez GitHub
commit cfc7dc8355
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
10 zmienionych plików z 88 dodań i 44 usunięć

Wyświetl plik

@ -1,7 +1,7 @@
# Remaining tasks before declaring 1.0
- add faq entry about range and antennas and rain
- first message sent is still doubled for some people
- disable software update button after update finishes
- let users set arbitrary params in android
- add a low level settings screen (let user change any of the RadioConfig parameters)

Wyświetl plik

@ -17,8 +17,8 @@ android {
applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 29
versionCode 10785 // format is Mmmss (where M is 1+the numeric major number
versionName "0.7.85"
versionCode 10787 // format is Mmmss (where M is 1+the numeric major number
versionName "0.7.87"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {

Wyświetl plik

@ -0,0 +1 @@
../../../../../meshtastic-esp32/release/latest/bins

Wyświetl plik

@ -772,7 +772,12 @@ class MainActivity : AppCompatActivity(), Logging,
if (model.meshService != null)
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
MeshService.startService(this) // Start the service so it stays running even after we unbind
try {
MeshService.startService(this) // Start the service so it stays running even after we unbind
} catch (ex: Exception) {
// Old samsung phones have a race condition andthis might rarely fail. Which is probably find because the bind will be sufficient most of the time
errormsg("Failed to start service from activity - but ignoring because bind will work ${ex.message}")
}
// ALSO bind so we can use the api
mesh.connect(this, MeshService.intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)

Wyświetl plik

@ -354,35 +354,40 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String
private var isFirstTime = true
private fun doDiscoverServicesAndInit() {
// FIXME - no need to discover services more than once - instead use lazy() to use them in future attempts
safe!!.asyncDiscoverServices { discRes ->
discRes.getOrThrow() // FIXME, instead just try to reconnect?
try {
discRes.getOrThrow()
service.serviceScope.handledLaunch {
try {
debug("Discovered services!")
delay(1000) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null
service.serviceScope.handledLaunch {
try {
debug("Discovered services!")
delay(1000) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null
/* if (isFirstTime) {
isFirstTime = false
throw BLEException("Faking a BLE failure")
} */
/* if (isFirstTime) {
isFirstTime = false
throw BLEException("Faking a BLE failure")
} */
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER)
// We treat the first send by a client as special
isFirstSend = true
// We treat the first send by a client as special
isFirstSend = true
// Now tell clients they can (finally use the api)
service.onConnect()
// Now tell clients they can (finally use the api)
service.onConnect()
// Immediately broadcast any queued packets sitting on the device
doReadFromRadio(true)
} catch (ex: BLEException) {
scheduleReconnect(
"Unexpected error in initial device enumeration, forcing disconnect $ex"
)
// Immediately broadcast any queued packets sitting on the device
doReadFromRadio(true)
} catch (ex: BLEException) {
scheduleReconnect(
"Unexpected error in initial device enumeration, forcing disconnect $ex"
)
}
}
} catch (ex: BLEException) {
scheduleReconnect(
"Unexpected error discovering services, forcing disconnect $ex"
)
}
}
}

Wyświetl plik

@ -1461,6 +1461,8 @@ class MeshService : Service(), Logging {
errormsg("Unable to update", ex)
null
}
debug("setFirmwareUpdateFilename $firmwareUpdateFilename")
}
private fun doFirmwareUpdate() {

Wyświetl plik

@ -85,8 +85,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
}
override fun toString(): String {
return super.toString()
return "Work:$tag"
}
/// Connection work items are treated specially
fun isConnect() = tag == "connect" || tag == "reconnect"
}
/**
@ -122,6 +125,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
private val STATUS_RELIABLE_WRITE_FAILED = 4403
private val STATUS_TIMEOUT = 4404
private val STATUS_NOSTART = 4405
private val STATUS_SIMFAILURE = 4406
private val gattCallback = object : BluetoothGattCallback() {
@ -157,7 +161,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
if (oldstate == BluetoothProfile.STATE_CONNECTED) {
info("Lost connection - aborting current work: $currentWork")
dropAndReconnect()
// If we get a disconnect, just try again otherwise fail all current operations
if (currentWork?.isConnect() == true)
dropAndReconnect()
else
lostConnection("lost connection")
} else if (status == 133) {
// We were not previously connected and we just failed with our non-auto connection attempt. Therefore we now need
// to do an autoconnection attempt. When that attempt succeeds/fails the normal callbacks will be called
@ -285,6 +293,12 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
}
}
// To test loss of BLE faults we can randomly fail a certain % of all work items. We
// skip this for "connect" items because the handling for connection failure is special
var simFailures = false
var failPercent =
10 // 15% failure is unusably high because of constant reconnects, 7% somewhat usable, 10% pretty bad
private val failRandom = Random()
private var activeTimeout: Job? = null
@ -311,13 +325,22 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
isSettingMtu =
false // Most work is not doing MTU stuff, the work that is will re set this flag
val started = newWork.startWork()
if (!started) {
errormsg("Failed to start work, returned error status")
completeWork(
STATUS_NOSTART,
Unit
) // abandon the current attempt and try for another
val failThis =
simFailures && !newWork.isConnect() && failRandom.nextInt(100) < failPercent
if (failThis) {
errormsg("Simulating random work failure!")
completeWork(STATUS_SIMFAILURE, Unit)
} else {
val started = newWork.startWork()
if (!started) {
errormsg("Failed to start work, returned error status")
completeWork(
STATUS_NOSTART,
Unit
) // abandon the current attempt and try for another
}
}
}
}
@ -499,8 +522,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
}
}
/// Drop our current connection and then requeue a connect as needed
private fun dropAndReconnect() {
private fun lostConnection(reason: String) {
/*
Supposedly this reconnect attempt happens automatically
"If the connection was established through an auto connect, Android will
@ -511,7 +533,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
closeConnection()
*/
failAllWork(BLEException("Lost connection"))
failAllWork(BLEException(reason))
// Cancel any notifications - because when the device comes back it might have forgotten about us
notifyHandlers.clear()
@ -520,6 +542,11 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
debug("calling lostConnect handler")
it.invoke()
}
}
/// Drop our current connection and then requeue a connect as needed
private fun dropAndReconnect() {
lostConnection("lost connection, reconnecting")
// Queue a new connection attempt
val cb = connectionCallback

Wyświetl plik

@ -230,10 +230,12 @@ class SoftwareUpdateService : JobIntentService(), Logging {
val (region) = regionRegex.find(hwVer)?.destructured
?: throw Exception("Malformed hw version")
val name = "firmware/firmware-$mfg-$region-$curver.bin"
val base = "firmware-$mfg-$region-$curver.bin"
// Check to see if the file exists (some builds might not include update files for size reasons)
return if (!context.assets.list(name).isNullOrEmpty())
name
val firmwareFiles = context.assets.list("firmware") ?: arrayOf()
return if (firmwareFiles.contains(base))
"firmware/$base"
else
null
}

Wyświetl plik

@ -484,10 +484,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
updateProgressBar.progress = service.updateStatus
delay(2000) // Only check occasionally
}
val isSuccess = (service.updateStatus == -1)
scanStatusText.text =
if (service.updateStatus == -1) "Update successful" else "Update failed"
if (isSuccess) "Update successful" else "Update failed"
updateProgressBar.isEnabled = false
updateFirmwareButton.isEnabled = true
updateFirmwareButton.isEnabled = !isSuccess
}
}
}
@ -504,7 +506,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
// If actively connected possibly let the user update firmware
val info = model.myNodeInfo.value
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate) {
if (connected == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate && info.couldUpdate) {
updateFirmwareButton.visibility = View.VISIBLE
updateFirmwareButton.text =
getString(R.string.update_to).format(getString(R.string.cur_firmware_version))

@ -1 +1 @@
Subproject commit 10d3b2e62b26d41b9b2568eefb3c207442c1cc5c
Subproject commit 95c5a9aa950f917857a3cc0c7cd84a4a56993032