2020-03-24 13:48:22 -07:00
|
|
|
package com.geeksville.mesh.model
|
|
|
|
|
|
|
|
|
|
import android.graphics.Bitmap
|
|
|
|
|
import android.net.Uri
|
|
|
|
|
import android.util.Base64
|
|
|
|
|
import com.geeksville.mesh.MeshProtos
|
|
|
|
|
import com.google.zxing.BarcodeFormat
|
|
|
|
|
import com.google.zxing.MultiFormatWriter
|
|
|
|
|
import com.journeyapps.barcodescanner.BarcodeEncoder
|
|
|
|
|
import java.net.MalformedURLException
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data class Channel(
|
2020-04-09 16:33:42 -07:00
|
|
|
val settings: MeshProtos.ChannelSettings = MeshProtos.ChannelSettings.getDefaultInstance()
|
2020-03-24 13:48:22 -07:00
|
|
|
) {
|
|
|
|
|
companion object {
|
2020-06-12 20:26:10 -07:00
|
|
|
// Note: this string _SHOULD NOT BE LOCALIZED_ because it directly hashes to values used on the device for the default channel name.
|
|
|
|
|
val defaultChannelName = "Default"
|
|
|
|
|
|
2020-03-24 13:48:22 -07:00
|
|
|
// Placeholder when emulating
|
|
|
|
|
val emulated = Channel(
|
2020-06-12 20:26:10 -07:00
|
|
|
MeshProtos.ChannelSettings.newBuilder().setName(defaultChannelName)
|
2020-03-24 13:48:22 -07:00
|
|
|
.setModemConfig(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const val prefix = "https://www.meshtastic.org/c/"
|
|
|
|
|
|
|
|
|
|
private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP
|
|
|
|
|
|
|
|
|
|
private fun urlToSettings(url: Uri): MeshProtos.ChannelSettings {
|
|
|
|
|
val urlStr = url.toString()
|
|
|
|
|
val pathRegex = Regex("$prefix(.*)")
|
|
|
|
|
val (base64) = pathRegex.find(urlStr)?.destructured
|
|
|
|
|
?: throw MalformedURLException("Not a meshtastic URL")
|
|
|
|
|
val bytes = Base64.decode(base64, base64Flags)
|
|
|
|
|
|
|
|
|
|
return MeshProtos.ChannelSettings.parseFrom(bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor(url: Uri) : this(urlToSettings(url))
|
|
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
val name: String get() = settings.name
|
|
|
|
|
val modemConfig: MeshProtos.ChannelSettings.ModemConfig get() = settings.modemConfig
|
|
|
|
|
|
2020-03-24 13:48:22 -07:00
|
|
|
/// Can this channel be changed right now?
|
|
|
|
|
var editable = false
|
|
|
|
|
|
|
|
|
|
/// Return an URL that represents the current channel values
|
|
|
|
|
fun getChannelUrl(): Uri {
|
|
|
|
|
// If we have a valid radio config use it, othterwise use whatever we have saved in the prefs
|
|
|
|
|
|
2020-04-19 16:24:47 -07:00
|
|
|
val channelBytes = settings.toByteArray() ?: ByteArray(0) // if unset just use empty
|
2020-03-24 13:48:22 -07:00
|
|
|
val enc = Base64.encodeToString(channelBytes, base64Flags)
|
|
|
|
|
|
|
|
|
|
return Uri.parse("$prefix$enc")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun getChannelQR(): Bitmap {
|
|
|
|
|
val multiFormatWriter = MultiFormatWriter()
|
|
|
|
|
|
|
|
|
|
val bitMatrix =
|
|
|
|
|
multiFormatWriter.encode(getChannelUrl().toString(), BarcodeFormat.QR_CODE, 192, 192);
|
|
|
|
|
val barcodeEncoder = BarcodeEncoder()
|
|
|
|
|
return barcodeEncoder.createBitmap(bitMatrix)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* a nice readable description of modem configs
|
|
|
|
|
*/
|
|
|
|
|
fun MeshProtos.ChannelSettings.ModemConfig.toHumanString(): String = when (this) {
|
|
|
|
|
MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128 -> "Medium range (but fast)"
|
|
|
|
|
MeshProtos.ChannelSettings.ModemConfig.Bw500Cr45Sf128 -> "Short range (but fast)"
|
|
|
|
|
MeshProtos.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512 -> "Long range (but slower)"
|
|
|
|
|
MeshProtos.ChannelSettings.ModemConfig.Bw125Cr48Sf4096 -> "Very long range (but slow)"
|
|
|
|
|
else -> this.toString()
|
|
|
|
|
}
|