From 97961f274f991aba8ab5eb6a086e54d5e29ba77d Mon Sep 17 00:00:00 2001 From: geeksville Date: Sun, 21 Jun 2020 13:08:35 -0700 Subject: [PATCH 1/4] Japanese tweak from @neklan --- app/src/main/res/values-ja/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 701138484..2a7364a21 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -48,7 +48,7 @@ シェア 切断 スリープ - 接続済み:%s人中%sオンライン + 接続済み:%s人オンライン%s人中 ネットワーク内のノードリスト ファームウェアアップデート Meshtasticデバイスに接続しました。(%s) From 6001d22837654468c6d880330448f9cc2a0270bf Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 22 Jun 2020 16:30:40 -0700 Subject: [PATCH 2/4] @zone added Turkish translations! --- README.md | 1 + app/build.gradle | 2 +- app/src/main/res/values-tr/strings.xml | 70 ++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/values-tr/strings.xml diff --git a/README.md b/README.md index 2d3cd03ad..e28b8d983 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ This project is the work of volunteers: * @NEKLAN: Contributed Japanese translation. * @Ohcdh: Contributed Irish and Italian translations. * @Slavino: Contributed Slovak translation. +* @Zone: Contributed Turkish translation. Copyright 2019, Geeksville Industries, LLC. GPL V3 license diff --git a/app/build.gradle b/app/build.gradle index 5ced5f7df..2c161247a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,7 +35,7 @@ android { defaultConfig { // We have to list all translated languages here, because some of our libs have bogus languages that google play // doesn't like and we need to strip them (gr) - resConfigs "cs", "de", "en", "es", "fi", "fr", "ga", "it", "ja", "nl", "ru", "sk", "sv", "zh" + resConfigs "cs", "de", "en", "es", "fi", "fr", "ga", "it", "ja", "nl", "ru", "sk", "sv", "tr", "zh" // Needed to make mapbox work inside the firebase testlab - FIXME, alas, still doesn't work ndk { diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml new file mode 100644 index 000000000..3dfccfb5a --- /dev/null +++ b/app/src/main/res/values-tr/strings.xml @@ -0,0 +1,70 @@ + + + Ayarla + Kanal Adı + Kanal Seçenekleri + Paylaş Düğmesi + QR kodu + Kaldır + Bağlantı durumu + uygulama ikonu + Bilinmeyen kullanıcı adı + Avatar + hey I found the cache, it is over here next to the big tiger. I\'m kinda scared. + Metni Gönder + Telefonu, henüz Meshtastic uyumlu bir telsiz ile eşleştirmediniz. Bir cihazla eşleştirin ve kullanıcı adınızı belirleyin lütfen.\n\nAçık kaynaklı bu uygulama şu an alfa-test\'i aşamasında, problemler görürseniz forum\'da lütfen paylaşınız: meshtastic.discourse.group.\n\nDaha fazla bilgi için internet sitemizi ziyaret ediniz - www.meshtastic.org. + Kullanıcı adını kaldır + Adınız + Anonim kullanim istatistikleri ve hata raporları. + Meshtastic cihazları aranıyor... + Bu cihaz bluetooth erişimi gerektiriyor. Lütfen Android ayarlarından izin veriniz. + Hata - bu uygulama bluetooth gerektiriyor + Eşleşme başlatılıyor + Eşleşme başarız + Meshtastic mesh ağına bağlanmak için adres + Kabul et + İptal + Kanalı değiştir + Kanalı değiştirmek istediğinize emin misiniz? Yeni kanal ayarlarını paylaşana dek tüm node\'lar ile iletişim sonlanacak. + Yeni Kanal Adresi alındı + \'%s\' kanalına geçmek istiyor musunuz? + Analitik raporları kapattınız. Harita sağlayıcımız (mapbox) ücretsiz kullanım paketi için analitik raporları gerektiriyor maalesef. Bu yüzden harita görünümü pasif hale getirdik.\n\n + Haritayı görmek istiyorsanız, Ayarlar bölümünden analitik raporları aktif hale getirmeniz gerekiyor. (ayrıca, şu an bunun için uygulamayı tümüyle kapatıp yeniden açmanız gerekebilir).\n\n + Eğer mapbox için ödeme yapmamız (ya da başka bir harita sağlayıcıya geçme) konusunda ilgiliyseniz, lütfen meshtastic.discourse.group sayfasında paylaşınız. + Gerekli bir izin eksik, Meshtastic düzgün çalışamayacak. Lütfen Android ayarlarından izni aktif hale getiriniz. + Telsiz uyku durumundaydı, kanal değiştirilemedi + Hata Bildir + Hata Bildir + Hata bildirmek istediğinizden emin misiniz? Hata bildirdikten sonra, lütfen meshtastic.discourse.group sayfasında paylaşınız ki raporu bulgularınızla eşleştirebilelim. + Bildir + Telsiz seçiniz + Şu anda %s telsizi ile eşleşmiş durumdasınız. + Henüz bir telsiz ile eşleşmediniz. + Telsizi değiştir + Cihazı Android ayarlarında eşleştiriniz lütfen. + Eşleşme tamamlandı, servis başlatılıyor + Eşleşme başarısız, lütfen tekrar seçiniz + Konum erişimi kapalı, konum mesh ağına paylaşılamıyor. + Paylaş + Bağlantı sonlandı + Cihaz uyku durumunda + Bağlandı: %s / %s online + Ağdaki node listesi + Yazılım güncelle + Radyoya bağlandı + (%s) telsizine bağlandı + Bağlı değil, aşağıdan bir radyo seçiniz + Telsize bağlandı, ancak uyku durumunda + %s\'e güncelle + Uygulama çok eski + Uygulamayı Google Play store (ya da GitHub)\'da güncellemelisiniz. Bu telsiz ile haberleşmek için uygualama çok eski. + Hiçbiri (kapat) + Kısa menzilli (ama hızlı) + Orta menzilli (ama hızlı) + Uzun menzilli (ama yavaş) + Çok uzun menzilli (ama yavaş) + TANIMLANAMADI + Meshtastic Servis Bildirimleri + Android ayarlarında konum servislerine izin vermelisiniz + Hakkında + \ No newline at end of file From d78932d6dabb5f8a9e452dadae89c1a3ed6a3fe3 Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 22 Jun 2020 17:14:29 -0700 Subject: [PATCH 3/4] Proper version checking and enable BLE software update for new devices --- .../mesh/service/SoftwareUpdateService.kt | 152 +++++++++++------- 1 file changed, 90 insertions(+), 62 deletions(-) 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 6799630a0..cf0c12613 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt @@ -9,6 +9,7 @@ import androidx.core.app.JobIntentService import com.geeksville.android.Logging import com.geeksville.mesh.MainActivity import com.geeksville.mesh.R +import com.geeksville.util.Exceptions import com.geeksville.util.exceptionReporter import java.util.* import java.util.zip.CRC32 @@ -173,21 +174,42 @@ class SoftwareUpdateService : JobIntentService(), Logging { ) } + /** + * Convert a version string of the form 1.23.57 to a comparable integer of + * the form 12357. + * + * Or throw an exception if the string can not be parsed + */ + fun verStringToInt(s: String): Int { + // Allow 1 to two digits per match + val match = + Regex("(\\d{1,2}).(\\d{1,2}).(\\d{1,2})").find(s) + ?: throw Exception("Can't parse version $s") + val (major, minor, build) = match.destructured + return major.toInt() * 1000 + minor.toInt() * 100 + build.toInt() + } + /** Return true if we thing the firmwarte shoulde be updated + * + * @param swVer the version of the software running on the target */ fun shouldUpdate( context: Context, swVer: String - ): Boolean { - val curver = context.getString(R.string.cur_firmware_version) + ): Boolean = try { + val curVer = verStringToInt(context.getString(R.string.cur_firmware_version)) + val minVer = + verStringToInt("0.7.8") // The oldest device version with a working software update service // If the user is running a development build we never do an automatic update - val isDevBuild = swVer.isEmpty() || swVer == "unset" + val deviceVersion = + verStringToInt(if (swVer.isEmpty() || swVer == "unset") "99.99.99" else swVer) - // FIXME, instead compare version strings carefully to see if less than - val needsUpdate = (curver != swVer) - - return needsUpdate && !isDevBuild && false // temporarily disabled because it fails occasionally + (curVer > deviceVersion) && (deviceVersion >= minVer) + // true + } catch (ex: Exception) { + Exceptions.report(ex, "Error finding swupdate info") + false // If we fail parsing our update info } /** Return the filename this device needs to use as an update (or null if no update needed) @@ -237,71 +259,77 @@ class SoftwareUpdateService : JobIntentService(), Logging { * you can use it for the software update. */ fun doUpdate(context: Context, sync: SafeBluetooth, assetName: String) { - val service = sync.gatt!!.services.find { it.uuid == SW_UPDATE_UUID }!! + try { + val g = sync.gatt!! + val service = g.services.find { it.uuid == SW_UPDATE_UUID }!! - info("Starting firmware update for $assetName") + info("Starting firmware update for $assetName") - progress = 0 - val totalSizeDesc = service.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER) - val dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER) - val crc32Desc = service.getCharacteristic(SW_UPDATE_CRC32_CHARACTER) - val updateResultDesc = service.getCharacteristic(SW_UPDATE_RESULT_CHARACTER) + progress = 0 + val totalSizeDesc = service.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER) + val dataDesc = service.getCharacteristic(SW_UPDATE_DATA_CHARACTER) + val crc32Desc = service.getCharacteristic(SW_UPDATE_CRC32_CHARACTER) + val updateResultDesc = service.getCharacteristic(SW_UPDATE_RESULT_CHARACTER) - context.assets.open(assetName).use { firmwareStream -> - val firmwareCrc = CRC32() - var firmwareNumSent = 0 - val firmwareSize = firmwareStream.available() + context.assets.open(assetName).use { firmwareStream -> + val firmwareCrc = CRC32() + var firmwareNumSent = 0 + val firmwareSize = firmwareStream.available() - // Start the update by writing the # of bytes in the image - sync.writeCharacteristic( - totalSizeDesc, - toNetworkByteArray(firmwareSize, BluetoothGattCharacteristic.FORMAT_UINT32) - ) + // Start the update by writing the # of bytes in the image + sync.writeCharacteristic( + totalSizeDesc, + toNetworkByteArray(firmwareSize, BluetoothGattCharacteristic.FORMAT_UINT32) + ) - // Our write completed, queue up a readback - val totalSizeReadback = sync.readCharacteristic(totalSizeDesc) - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) - if (totalSizeReadback == 0) // FIXME - handle this case - throw Exception("Device rejected file size") + // Our write completed, queue up a readback + val totalSizeReadback = sync.readCharacteristic(totalSizeDesc) + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) + if (totalSizeReadback == 0) // FIXME - handle this case + throw Exception("Device rejected file size") - // Send all the blocks - while (firmwareNumSent < firmwareSize) { - progress = firmwareNumSent * 100 / firmwareSize - debug("sending block ${progress}%") - var blockSize = 512 - 3 // Max size MTU excluding framing + // Send all the blocks + while (firmwareNumSent < firmwareSize) { + progress = firmwareNumSent * 100 / firmwareSize + debug("sending block ${progress}%") + var blockSize = 512 - 3 // Max size MTU excluding framing - if (blockSize > firmwareStream.available()) - blockSize = firmwareStream.available() - val buffer = ByteArray(blockSize) + if (blockSize > firmwareStream.available()) + blockSize = firmwareStream.available() + val buffer = ByteArray(blockSize) - // slightly expensive to keep reallocing this buffer, but whatever - logAssert(firmwareStream.read(buffer) == blockSize) - firmwareCrc.update(buffer) + // slightly expensive to keep reallocing this buffer, but whatever + logAssert(firmwareStream.read(buffer) == blockSize) + firmwareCrc.update(buffer) - sync.writeCharacteristic(dataDesc, buffer) - firmwareNumSent += blockSize + sync.writeCharacteristic(dataDesc, buffer) + firmwareNumSent += blockSize + } + + // We have finished sending all our blocks, so post the CRC so our state machine can advance + val c = firmwareCrc.value + info("Sent all blocks, crc is $c") + sync.writeCharacteristic( + crc32Desc, + toNetworkByteArray(c.toInt(), BluetoothGattCharacteristic.FORMAT_UINT32) + ) + + // we just read the update result if !0 we have an error + val updateResult = + sync.readCharacteristic(updateResultDesc) + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + if (updateResult != 0) { + progress = -2 + throw Exception("Device update failed, reason=$updateResult") + } + + // Device will now reboot + + progress = -1 // success } - - // We have finished sending all our blocks, so post the CRC so our state machine can advance - val c = firmwareCrc.value - info("Sent all blocks, crc is $c") - sync.writeCharacteristic( - crc32Desc, - toNetworkByteArray(c.toInt(), BluetoothGattCharacteristic.FORMAT_UINT32) - ) - - // we just read the update result if !0 we have an error - val updateResult = - sync.readCharacteristic(updateResultDesc) - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) - if (updateResult != 0) { - progress = -2 - throw Exception("Device update failed, reason=$updateResult") - } - - // Device will now reboot - - progress = -1 // success + } catch (ex: BLEException) { + progress = -3 + throw ex // Unexpected BLE exception } } } From ca6de339438364963428e16146765d367ce488e5 Mon Sep 17 00:00:00 2001 From: geeksville Date: Wed, 24 Jun 2020 14:58:56 -0700 Subject: [PATCH 4/4] Allow user to enter only a very restricted list of channel name chars (for now - possibly loosen in the future - someone reported the device code didn't like odd characters, and we definitely don't want anything >127). Also, shrink length to 11 chars (which is 12 including the nul terminator on the device side (current limit in mesh.options). --- app/src/main/res/layout/channel_fragment.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/channel_fragment.xml b/app/src/main/res/layout/channel_fragment.xml index 9a27e3c4b..d2f411259 100644 --- a/app/src/main/res/layout/channel_fragment.xml +++ b/app/src/main/res/layout/channel_fragment.xml @@ -20,9 +20,10 @@ android:id="@+id/channelNameEdit" android:layout_width="match_parent" android:layout_height="wrap_content" + android:digits="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890- " android:hint="@string/channel_name" android:imeOptions="actionDone" - android:maxLength="12" + android:maxLength="11" android:singleLine="true" android:text="@string/unset" />