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)
+ }
+}