From c4439eb34cadbf330e6dc5565a0a9a288039ba27 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 10 Dec 2020 09:23:02 +0800 Subject: [PATCH] WIP use new position api --- .../geeksville/mesh/service/DeviceVersion.kt | 33 +++++++++++++++++++ .../geeksville/mesh/service/MeshService.kt | 33 ++++++++++++++----- .../mesh/service/SoftwareUpdateService.kt | 31 ++++------------- 3 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/com/geeksville/mesh/service/DeviceVersion.kt diff --git a/app/src/main/java/com/geeksville/mesh/service/DeviceVersion.kt b/app/src/main/java/com/geeksville/mesh/service/DeviceVersion.kt new file mode 100644 index 00000000..13ef461e --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/service/DeviceVersion.kt @@ -0,0 +1,33 @@ +package com.geeksville.mesh.service + +import com.geeksville.android.Logging + +/** + * Provide structured access to parse and compare device version strings + */ +data class DeviceVersion(val asString: String): Comparable, Logging { + + val asInt get() = try { + verStringToInt(asString) + } catch(e: Exception) { + warn("Exception while parsing version '$asString', assuming version 0") + 0 + } + + /** + * 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 + */ + private 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() + } + + override fun compareTo(other: DeviceVersion): Int = asInt - other.asInt +} \ No newline at end of file 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 c7d03f68..c294e8ac 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -91,6 +91,9 @@ class MeshService : Service(), Logging { private var packetRepo: PacketRepository? = null private var fusedLocationClient: FusedLocationProviderClient? = null + // If we've ever read a valid region code from our device it will be here + var curRegionValue = MeshProtos.RegionCode.Unset_VALUE + val radio = ServiceClient { IRadioInterfaceService.Stub.asInterface(it).apply { // Now that we are connected to the radio service, tell it to connect to the radio @@ -418,6 +421,8 @@ class MeshService : Service(), Logging { /// END OF MODEL /// + val deviceVersion get() = DeviceVersion(myNodeInfo?.firmwareVersion ?: "") + /// Map a nodenum to a node, or throw an exception if not found private fun toNodeInfo(n: Int) = nodeDBbyNodeNum[n] ?: throw NodeNumNotFoundException( n @@ -555,12 +560,15 @@ class MeshService : Service(), Logging { } } + /// Syntactic sugar to create data subpackets + private fun makeData(portNum: Int, bytes: ByteString) = MeshProtos.Data.newBuilder().also { + it.portnumValue = portNum + it.payload = bytes + }.build() + private fun toMeshPacket(p: DataPacket): MeshPacket { return buildMeshPacket(p.to!!, id = p.id, wantAck = true) { - data = MeshProtos.Data.newBuilder().also { - it.portnumValue = p.dataType - it.payload = ByteString.copyFrom(p.bytes) - }.build() + data = makeData(p.dataType, ByteString.copyFrom(p.bytes)) } } @@ -1066,7 +1074,10 @@ class MeshService : Service(), Logging { hwModel, firmwareVersion, firmwareUpdateFilename != null, - SoftwareUpdateService.shouldUpdate(this@MeshService, firmwareVersion), + SoftwareUpdateService.shouldUpdate( + this@MeshService, + DeviceVersion(firmwareVersion) + ), currentPacketId.toLong() and 0xffffffffL, if (nodeNumBits == 0) 8 else nodeNumBits, if (packetIdBits == 0) 8 else packetIdBits, @@ -1100,8 +1111,7 @@ class MeshService : Service(), Logging { } } - // If we've ever read a valid region code from our device it will be here - var curRegionValue = MeshProtos.RegionCode.Unset_VALUE + /** * If we are updating nodes we might need to use old (fixed by firmware build) @@ -1227,7 +1237,14 @@ class MeshService : Service(), Logging { val packet = newMeshPacketTo(destNum) packet.decoded = MeshProtos.SubPacket.newBuilder().also { - it.position = position + val isNewPositionAPI = deviceVersion >= DeviceVersion("1.20.0") // We changed position APIs with this version + if (isNewPositionAPI) { + // Use the new position as data format + it.data = makeData(Portnums.PortNum.POSITION_APP_VALUE, position.toByteString()) + } else { + // Send the old dedicated position subpacket + it.position = position + } it.wantResponse = wantResponse }.build() 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 5a4fe4b3..69d57639 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt @@ -186,20 +186,7 @@ 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 * @@ -207,15 +194,11 @@ class SoftwareUpdateService : JobIntentService(), Logging { */ fun shouldUpdate( context: Context, - swVer: String + deviceVersion: DeviceVersion ): Boolean = try { - val curVer = verStringToInt(context.getString(R.string.cur_firmware_version)) + val curVer = DeviceVersion(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 deviceVersion = - verStringToInt(if (swVer.isEmpty() || swVer == "unset") "99.99.99" else swVer) + DeviceVersion("0.7.8") // The oldest device version with a working software update service (curVer > deviceVersion) && (deviceVersion >= minVer) } catch (ex: Exception) { @@ -229,13 +212,13 @@ class SoftwareUpdateService : JobIntentService(), Logging { context: Context, mfg: String ): UpdateFilenames { - val curver = context.getString(R.string.cur_firmware_version) + val curVer = context.getString(R.string.cur_firmware_version) // Check to see if the file exists (some builds might not include update files for size reasons) val firmwareFiles = context.assets.list("firmware") ?: arrayOf() - val appLoad = "firmware-$mfg-$curver.bin" - val spiffs = "spiffs-$curver.bin" + val appLoad = "firmware-$mfg-$curVer.bin" + val spiffs = "spiffs-$curVer.bin" return UpdateFilenames( if (firmwareFiles.contains(appLoad))