diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 1638c5a2f..1991620cc 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -19,11 +19,12 @@ jobs:
- name: Load secrets
run: |
rm ./app/src/main/res/values/mapbox-token.xml
- echo -e "\n $MAPBOXTOKEN\n" > ./app/src/main/res/values/mapbox-token.xml
+ echo -e "\n $MAPBOX_ACCESS_TOKEN\n" > ./app/src/main/res/values/mapbox-token.xml
mkdir -p ~/.gradle
- echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOXTOKEN" >>~/.gradle/gradle.properties
+ echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOX_DOWNLOADS_TOKEN" >>~/.gradle/gradle.properties
env:
- MAPBOXTOKEN: ${{ secrets.MAPBOXTOKEN }}
+ MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
+ MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }}
- name: Mock files for CI
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6019b76f1..b8734afd9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -22,14 +22,15 @@ jobs:
rm ./app/google-services.json
echo $GSERVICES > ./app/google-services.json
rm ./app/src/main/res/values/mapbox-token.xml
- echo -e "\n $MAPBOXTOKEN\n" > ./app/src/main/res/values/mapbox-token.xml
+ echo -e "\n $MAPBOX_ACCESS_TOKEN\n" > ./app/src/main/res/values/mapbox-token.xml
mkdir -p ~/.gradle
- echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOXTOKEN" >> ~/.gradle/gradle.properties
+ echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOX_DOWNLOADS_TOKEN" >> ~/.gradle/gradle.properties
echo $KEYSTORE | base64 -di > ./app/$KEYSTORE_FILENAME
echo "$KEYSTORE_PROPERTIES" > ./keystore.properties
env:
GSERVICES: ${{ secrets.GSERVICES }}
- MAPBOXTOKEN: ${{ secrets.MAPBOXTOKEN }}
+ MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
+ MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }}
KEYSTORE: ${{ secrets.KEYSTORE }}
KEYSTORE_FILENAME: ${{ secrets.KEYSTORE_FILENAME }}
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
diff --git a/app/build.gradle b/app/build.gradle
index e038e8315..90ca7c514 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 // 30 can't work until an explicit location permissions dialog is added
- versionCode 20259 // format is Mmmss (where M is 1+the numeric major number
- versionName "1.2.59"
+ versionCode 20260 // format is Mmmss (where M is 1+the numeric major number
+ versionName "1.2.60"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// per https://developer.android.com/studio/write/vector-asset-studio
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 fe3672049..a28c52a9b 100644
--- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
+++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
@@ -1309,13 +1309,14 @@ class MeshService : Service(), Logging {
if (asStr != null)
hwModelStr = asStr
}
+ setFirmwareUpdateFilename(hwModelStr)
val mi = with(myInfo) {
MyNodeInfo(
myNodeNum,
hasGps,
hwModelStr,
firmwareVersion,
- firmwareUpdateFilename != null,
+ firmwareUpdateFilename?.appLoad != null && firmwareUpdateFilename?.spiffs != null,
isBluetoothInterface && SoftwareUpdateService.shouldUpdate(
this@MeshService,
DeviceVersion(firmwareVersion)
@@ -1328,9 +1329,7 @@ class MeshService : Service(), Logging {
airUtilTx
)
}
-
newMyNodeInfo = mi
- setFirmwareUpdateFilename(mi)
}
}
@@ -1670,12 +1669,12 @@ class MeshService : Service(), Logging {
/***
* Return the filename we will install on the device
*/
- private fun setFirmwareUpdateFilename(info: MyNodeInfo) {
+ private fun setFirmwareUpdateFilename(model: String?) {
firmwareUpdateFilename = try {
- if (info.firmwareVersion != null && info.model != null)
+ if (model != null)
SoftwareUpdateService.getUpdateFilename(
this,
- info.model
+ model
)
else
null
diff --git a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt
index 8326a5168..7fe354101 100644
--- a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt
+++ b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt
@@ -243,7 +243,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
false // If we fail parsing our update info
}
- /** Return a Pair of apploadfilename, spiffs filename this device needs to use as an update (or null if no update needed)
+ /** Return a Pair of appload filename, spiffs filename this device needs to use as an update (or null if no update needed)
*/
fun getUpdateFilename(
context: Context,
@@ -290,9 +290,15 @@ class SoftwareUpdateService : JobIntentService(), Logging {
* you can use it for the software update.
*/
fun doUpdate(context: Context, sync: SafeBluetooth, assets: UpdateFilenames) {
+ // calculate total firmware size (spiffs + appLoad)
+ var totalFirmwareSize = 0
+ if (assets.appLoad != null && assets.spiffs != null) {
+ totalFirmwareSize += context.assets.open(assets.appLoad).available()
+ totalFirmwareSize += context.assets.open(assets.spiffs).available()
+ }
// we must attempt spiffs first, because if we update the appload the device will reboot afterwards
try {
- assets.spiffs?.let { doUpdate(context, sync, it, FLASH_REGION_SPIFFS) }
+ assets.spiffs?.let { doUpdate(context, sync, it, FLASH_REGION_SPIFFS, totalFirmwareSize) }
} catch (_: BLECharacteristicNotFoundException) {
// If we can't update spiffs (because not supported by target), do not fail
errormsg("Ignoring failure to update spiffs on old appload")
@@ -301,7 +307,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
errormsg("Device rejected invalid spiffs partition")
}
- assets.appLoad?.let { doUpdate(context, sync, it, FLASH_REGION_APPLOAD) }
+ assets.appLoad?.let { doUpdate(context, sync, it, FLASH_REGION_APPLOAD, totalFirmwareSize) }
sendProgress(context, ProgressSuccess, true)
}
@@ -317,7 +323,8 @@ class SoftwareUpdateService : JobIntentService(), Logging {
context: Context,
sync: SafeBluetooth,
assetName: String,
- flashRegion: Int = FLASH_REGION_APPLOAD
+ flashRegion: Int = FLASH_REGION_APPLOAD,
+ totalFirmwareSize: Int = 0
) {
val isAppload = flashRegion == FLASH_REGION_APPLOAD
@@ -378,13 +385,15 @@ class SoftwareUpdateService : JobIntentService(), Logging {
// Send all the blocks
var oldProgress = -1 // used to limit # of log spam
while (firmwareNumSent < firmwareSize) {
- // If we are doing the spiffs partition, we limit progress to a max of 50%, so that the user doesn't think we are done
- // yet
- val maxProgress = if (flashRegion != FLASH_REGION_APPLOAD)
- 50 else 100
+ // If we are doing the spiffs partition, we limit progress to a max of maxProgress
+ // when updating the appload partition, progress from (100 - maxProgress) to 100%
+ // maxProgress = spiffs% = 100% - appLoad%; (int * 10 + 5) / 10 used for rounding
+ val maxProgress = ((firmwareSize * 1000 / totalFirmwareSize) + 5) / 10
+ val minProgress = if (flashRegion != FLASH_REGION_APPLOAD)
+ 0 else (100 - maxProgress)
sendProgress(
context,
- firmwareNumSent * maxProgress / firmwareSize,
+ minProgress + firmwareNumSent * maxProgress / firmwareSize,
isAppload
)
if (progress != oldProgress) {
diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
index 89717f296..83fd0561f 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
@@ -24,6 +24,7 @@ import android.widget.*
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
+import com.geeksville.analytics.DataPair
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.hideKeyboard
@@ -474,6 +475,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
model.meshService?.let { service ->
debug("User started firmware update")
+ GeeksvilleApplication.analytics.track(
+ "firmware_update",
+ DataPair("content_type", "start")
+ )
binding.updateFirmwareButton.isEnabled = false // Disable until things complete
binding.updateProgressBar.visibility = View.VISIBLE
binding.updateProgressBar.progress = 0 // start from scratch
@@ -515,6 +520,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
} else
when (progress) {
ProgressSuccess -> {
+ GeeksvilleApplication.analytics.track(
+ "firmware_update",
+ DataPair("content_type", "success")
+ )
binding.scanStatusText.setText(R.string.update_successful)
binding.updateProgressBar.visibility = View.GONE
}
@@ -523,6 +532,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
binding.updateProgressBar.visibility = View.GONE
}
else -> {
+ GeeksvilleApplication.analytics.track(
+ "firmware_update",
+ DataPair("content_type", "failure")
+ )
binding.scanStatusText.setText(R.string.update_failed)
binding.updateProgressBar.visibility = View.VISIBLE
}