From bd796524b95bf5523ac24ca1c76dd7bc47e89b76 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 27 Feb 2021 12:04:44 +0800 Subject: [PATCH] channelset wip --- .idea/dictionaries/kevinh.xml | 1 + app/src/main/AndroidManifest.xml | 6 +- .../java/com/geeksville/mesh/model/Channel.kt | 49 +----------- .../com/geeksville/mesh/model/ChannelSet.kt | 75 +++++++++++++++++++ 4 files changed, 80 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt diff --git a/.idea/dictionaries/kevinh.xml b/.idea/dictionaries/kevinh.xml index 9de6060e7..56d3af4f2 100644 --- a/.idea/dictionaries/kevinh.xml +++ b/.idea/dictionaries/kevinh.xml @@ -5,6 +5,7 @@ errormsg geeksville meshtastic + protobuf \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 421034192..997db7e0f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -133,7 +133,7 @@ @@ -143,11 +143,11 @@ + android:pathPrefix="/d/" /> + android:pathPrefix="/D/" /> diff --git a/app/src/main/java/com/geeksville/mesh/model/Channel.kt b/app/src/main/java/com/geeksville/mesh/model/Channel.kt index 54886c7e5..d19faed8e 100644 --- a/app/src/main/java/com/geeksville/mesh/model/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/Channel.kt @@ -20,7 +20,7 @@ data class Channel( companion object { // Note: this string _SHOULD NOT BE LOCALIZED_ because it directly hashes to values used on the device for the default channel name. // FIXME - make this work with new channel name system - val defaultChannelName = "Default" + const val defaultChannelName = "Default" // These bytes must match the well known and not secret bytes used the default channel AES128 key device code val channelDefaultKey = byteArrayOfInts( @@ -33,27 +33,8 @@ data class Channel( MeshProtos.ChannelSettings.newBuilder().setName(defaultChannelName) .setModemConfig(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build() ) - - const val prefix = "https://www.meshtastic.org/c/#" - - private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING - - private fun urlToSettings(url: Uri): MeshProtos.ChannelSettings { - val urlStr = url.toString() - - // We no longer support the super old (about 0.8ish? verison of the URLs that don't use the # separator - I doubt - // anyone is still using that old format - val pathRegex = Regex("$prefix(.*)", RegexOption.IGNORE_CASE) - val (base64) = pathRegex.find(urlStr)?.destructured - ?: throw MalformedURLException("Not a meshtastic URL: ${urlStr.take(40)}") - val bytes = Base64.decode(base64, base64Flags) - - return MeshProtos.ChannelSettings.parseFrom(bytes) - } } - constructor(url: Uri) : this(urlToSettings(url)) - /// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec val name: String get() = if (settings.name.isEmpty()) { @@ -106,32 +87,4 @@ data class Channel( return "#${name}-${suffix}" } - - /// Can this channel be changed right now? - var editable = false - - /// Return an URL that represents the current channel values - /// @param upperCasePrefix - portions of the URL can be upper case to make for more efficient QR codes - fun getChannelUrl(upperCasePrefix: Boolean = false): Uri { - // If we have a valid radio config use it, othterwise use whatever we have saved in the prefs - - val channelBytes = settings.toByteArray() ?: ByteArray(0) // if unset just use empty - val enc = Base64.encodeToString(channelBytes, base64Flags) - - val p = if(upperCasePrefix) - prefix.toUpperCase() - else - prefix - return Uri.parse("$p$enc") - } - - fun getChannelQR(): Bitmap { - val multiFormatWriter = MultiFormatWriter() - - // We encode as UPPER case for the QR code URL because QR codes are more efficient for that special case - val bitMatrix = - multiFormatWriter.encode(getChannelUrl(true).toString(), BarcodeFormat.QR_CODE, 192, 192); - val barcodeEncoder = BarcodeEncoder() - return barcodeEncoder.createBitmap(bitMatrix) - } } diff --git a/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt b/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt new file mode 100644 index 000000000..1206af6e7 --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/model/ChannelSet.kt @@ -0,0 +1,75 @@ +package com.geeksville.mesh.model + +import android.graphics.Bitmap +import android.net.Uri +import android.util.Base64 +import com.geeksville.mesh.AppOnlyProtos +import com.geeksville.mesh.MeshProtos +import com.google.protobuf.ByteString +import com.google.zxing.BarcodeFormat +import com.google.zxing.MultiFormatWriter +import com.journeyapps.barcodescanner.BarcodeEncoder +import java.net.MalformedURLException + +/** Utility function to make it easy to declare byte arrays - FIXME move someplace better */ +fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() } + + +data class ChannelSet( + val protobuf: AppOnlyProtos.ChannelSet = AppOnlyProtos.ChannelSet.getDefaultInstance() +) { + companion object { + + // Placeholder when emulating + val emulated = ChannelSet( + AppOnlyProtos.ChannelSet.newBuilder().addSettings(Channel.emulated.settings).build() + ) + + const val prefix = "https://www.meshtastic.org/d/#" + + private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING + + private fun urlToChannels(url: Uri): AppOnlyProtos.ChannelSet { + val urlStr = url.toString() + + // We no longer support the super old (about 0.8ish? verison of the URLs that don't use the # separator - I doubt + // anyone is still using that old format + val pathRegex = Regex("$prefix(.*)", RegexOption.IGNORE_CASE) + val (base64) = pathRegex.find(urlStr)?.destructured + ?: throw MalformedURLException("Not a meshtastic URL: ${urlStr.take(40)}") + val bytes = Base64.decode(base64, base64Flags) + + return AppOnlyProtos.ChannelSet.parseFrom(bytes) + } + } + + constructor(url: Uri) : this(urlToChannels(url)) + + /// Can this channel be changed right now? + var editable = false + + /// Return an URL that represents the current channel values + /// @param upperCasePrefix - portions of the URL can be upper case to make for more efficient QR codes + fun getChannelUrl(upperCasePrefix: Boolean = false): Uri { + // If we have a valid radio config use it, othterwise use whatever we have saved in the prefs + + val channelBytes = protobuf.toByteArray() ?: ByteArray(0) // if unset just use empty + val enc = Base64.encodeToString(channelBytes, base64Flags) + + val p = if(upperCasePrefix) + prefix.toUpperCase() + else + prefix + return Uri.parse("$p$enc") + } + + fun getChannelQR(): Bitmap { + val multiFormatWriter = MultiFormatWriter() + + // We encode as UPPER case for the QR code URL because QR codes are more efficient for that special case + val bitMatrix = + multiFormatWriter.encode(getChannelUrl(true).toString(), BarcodeFormat.QR_CODE, 192, 192); + val barcodeEncoder = BarcodeEncoder() + return barcodeEncoder.createBitmap(bitMatrix) + } +}